Dumb Ways for Open Source Projects to Die
Bottom Line
Andrew Nesbitt, a package management and open source infrastructure expert, published a broad taxonomy of 25+ failure modes that kill open source projects - often while they still appear perfectly alive in package registries, pulling millions of weekly downloads. The post builds on his prior research showing 12.1% of critical open source repos are dead (713 out of 5,874), with dead packages' dependency edges totaling ~290 million. The key insight: a package resolving from a registry is no guarantee it's maintained, and lockfiles keep installing dead packages indefinitely because nobody checks.
Key Findings
- 25+ distinct failure modes catalogued across 8 categories: maintainer departure, maintainer present but ineffective, sabotage/capture, broken release pipelines, force majeure, the world moving on, and project splits
- 12.1% of critical open source repos are confirmed dead - meaning issues filed in the past year received zero response from anyone with write access
- ~1.7% of npm and 4% of Packagist packages point at a source repo that no longer exists
- The most depended-on dead packages are tiny npm utilities (like
fast-deep-equal) with 3–5 million dependent repos each - "Benevolent zombies" - repos with solid green contribution graphs where every commit is a bot (Dependabot, auto-merge) - fool recency-based health scores entirely
- 243 dead repos had PRs opened with the actual fix sitting unmerged, because nobody with merge access remained
Background
Andrew Nesbitt is a software engineer and package management expert who builds ecosyste.ms, open datasets and tools for critical open source infrastructure. He previously ran 24 Pull Requests, a project encouraging contributions to open source every December.
The "Dumb Ways" post is the capstone of a May 2026 series on his blog:
- Free as in Tribbles (May 7) - introduced the metaphor that modern dependency explosion is like Star Trek tribbles: each dependency "born pregnant" with its own dependencies
- Weekend at Bernie's (May 8) - data-driven analysis of how many critical packages are actually dead, using the ecosyste.Ms dataset of 8,606 packages across 16 package managers
- The Mismeasure of Open Source (May 9) - why all existing project health scoring systems share the same blind spots
- Centrality isn't Vitality (May 14) - why PageRank is a poor fit for dependency graphs
- Dumb Ways for an Open Source Project to Die (May 19) - the full taxonomy
The Taxonomy: 8 Categories of Death
1. The Maintainer Left
- Ghost maintainer - Most common death. No commits for years, issues unanswered. Could be abandonment or the maintainer died - indistinguishable externally
- Corporate orphan - Company built it, then pivoted/laid off team. GitHub org persists with logo, nobody remaining knows it's theirs
- Thesis orphan - Grad student graduated, lab lacks context. Academia provides zero incentive for maintaining software
- Funding cliff - Grant ended, maintainers returned to paying work. Funder's logo stays in README making it look healthy
- Hired away - Maintainer joined employer that doesn't allow outside OSS (e.G., Apple). Almost nobody hands over in time
- Succession deadlock - Maintainer unreachable, successors exist, but publish rights tied to inaccessible account. Registry dispute processes routinely take longer than forking and renaming
2. The Maintainer is Still There (But Ineffective)
- Burnout plateau - Typo fixes merged, but design decisions and debugging sit open indefinitely. Just enough activity to discourage forking, not enough to ship
- Benevolent zombie - Green contribution graph, every commit is a bot. Recency-based health scores rate this as fine - the whole problem with recency-based health scores
- Custody battle - Co-maintainers fallen out, each blocking the other. Users get two contradictory answers
- Tribal knowledge gone - Person who understood why left. Nobody confident touching load-bearing code
- Toxic gatekeeping - Hostile to new contributors. When maintainer stops, no successor pool exists - everyone who might take over was driven off years ago
3. Sabotage and Capture
- Captured maintainer - Hostile actor gains commit/publish access. The xz backdoor was a 2-year social engineering campaign. event-stream (2018): author handed package to volunteer who added wallet-stealer. Both projects looked healthier during capture because the new maintainer was doing the work
- Protestware - Maintainer deliberately breaks own package. colors/faker (2022), node-ipc (2022, targeted Russian IPs), left-pad (2016, unpublished entirely)
4. The Release Pipeline Broke
- Maintained-not-shipping - Fixes in git, nobody can cut release (lost account/2FA). Fix sits visible in repo, un-installable from registry
- Unreleasable main - Default branch drifted so far from last tag that releasing would be a breaking change. Gap widens until cutting release becomes its own project
- Build archaeology - Published artifacts work but nobody can reproduce them (gone CI service, deleted base image, tool version on lost laptop)
- Shadow-maintained - Real development in company's private monorepo; public repo gets periodic squashed dumps. Issues/PRs go nowhere
- Stranded major - Project on v4 and maintained, but ecosystem stuck on v1 (v2 was unmigrated rewrite)
- Registry orphan - Package resolves but source repo URL 404s
5. Force Majeure
- Sanctions-stranded - Registry blocked maintainer's jurisdiction or account frozen under export controls
- DMCA takedown - Copyright claim removes code. Project can survive if maintainers rewrite infringing parts, but often the project dies first
6. The World Moved On
- Platform-stranded - Project tied to dying platform (Bower components, jQuery plugins, PhoneGap)
- Superseded by native features - Package existed to polyfill something the language now does natively. Downloads continue from old lockfiles
7. Project Splits
- Fork limbo - Community fractured. Neither fork reaches escape velocity. Original loses contributors but name still resolves on registry
- License rug-pull - Project re-licenses, existing users can't upgrade. Forks form but lose the package name, SEO, and brand recognition
- Open-core hollowing - Core goes open source, valuable features become paid. Community edition stagnates while the open source badge remains
The Data Behind It (from "Weekend at Bernie's")
Dataset: 8,606 packages across 16 package managers → 5,874 distinct repositories
| Status | Percentage | Meaning |
|---|---|---|
| Active | 48.8% | Regular commits or release in past year |
| Dormant | 20.2% | Some maintainer response but no real development |
| Dead | 12.1% | Issues filed, zero response from anyone with write access |
| Unknown | 18.9% | No issues filed - responsiveness untested |
By ecosystem (dead %):
- Julia: 21.4% dead
- Go: 20.2% dead
- Hackage: 17.4% dead
- Packagist: 12.1% dead
- Cargo: 11.9% dead
- npm: 11.3% dead (highest absolute count - 181 dead repos)
- PyPI: 8.1% dead
1,414 dormant-or-dead packages have exactly one account with publish rights - a single point of failure.
The most depended-on dead packages (npm utilities, each with 3–5 million dependent repos): fast-deep-equal, fast-json-stable-stringify, utils-merge, require-directory. Nesbitt notes: "The most depended-on dead code is also the code with the least in it, which is simultaneously reassuring (very little to go wrong in forty lines) and the entire problem, since there's also very little reason for anyone to ever read those forty lines again."
The "Free as in Tribbles" Metaphor
Nesbitt argues the industry has moved through four phases of understanding "free" software:
- Free as in beer - costs nothing
- Free as in speech - liberty to modify
- Free as in puppy - free to take home, but needs ongoing care
- Free as in tribbles - each dependency is "born pregnant" with its own dependencies. A React starter pulls 1,000+ packages. A single date picker accounts for ~90 lockfile entries
At tribble scale, per-package stewardship is impossible. Dunbar's number (~150 relationships) puts a cognitive ceiling on manual oversight, and even the simplest projects exceed it before the first feature.
The existing tooling was built for the per-animal case: Dependabot files PRs per package, advisories identify one CVE in one version range of one library, SBOMs enumerate every tribble without indicating which compartments they've reached. "The unit you reason about stops being the package and becomes the lockfile, and after that every lockfile in the org."
Why This Matters Now
- AI vulnerability scanners are generating reports faster than maintainers can triage - flooding dead packages with CVEs nobody will fix
- AI-assisted coding has reduced forking cost to "roughly the cost of having the idea" - registries are filling with near-identical packages, each with its own bug surface
- Lockfiles freeze the dead in place - a dead package from 2019 keeps installing because
npm installdoesn't check if the maintainer is alive - No mechanism exists in any major package registry to mark a package as unmaintained or flag that its maintainer is unresponsive
Limitations and Critiques
- The "dead" classification requires evidence of non-response (issues filed, no answer). Many packages have no issues filed and are classified "unknown" - the real dead rate could be higher
- Go's 20% dead rate may be inflated by stale import paths when repos move while the module proxy keeps old paths installable
- The dataset covers the ecosyste.Ms "critical package set" - the top packages per registry. The long tail of smaller packages may have different patterns
- The taxonomy is descriptive, not prescriptive - it catalogues how projects die, but doesn't propose specific registry-level policy changes
- Some failure modes are genuinely hard to distinguish from outside (ghost maintainer who abandoned vs. Died; benevolent zombie who is actually maintaining via automation)
Open Questions
- Should package registries implement a "health check" mechanism that flags packages with no human maintainer response in N months?
- Can the xz incident's lessons be generalized into a framework for detecting social engineering attacks on packages?
- What would a "population-level dependency management" tool look like in practice?
- Is the tribble metaphor reversible - can the industry move back toward fewer, larger, better-maintained dependencies?
- How will AI-generated packages change the dynamics - will registries become even more crowded, or will AI help maintain existing packages?
Practical Takeaways
- For developers: Treat lockfiles as population management, not individual package relationships. You can't personally know all 1,000+ dependencies
- For maintainers: Set up succession plans before you need them. Add co-owners on registries, document tribal knowledge, archive repos you've abandoned
- For companies depending on OSS: Audit your dependency graph for dead packages. The fix your app needs may already exist as an unmerged PR on a dead repo
- For the ecosystem: Registries need mechanisms to signal unmaintained status beyond just archiving (which most dead maintainers never do)
- For security teams: Don't just scan for CVEs - scan for whether the package is alive. A CVE on a dead package with no fix path is a different risk than a CVE on an active project
Sources
- Andrew Nesbitt: Dumb Ways for an Open Source Project to Die
- Andrew Nesbitt: Weekend at Bernie's
- Andrew Nesbitt: Free as in Tribbles
- Andrew Nesbitt: The Mismeasure of Open Source
- Andrew Nesbitt: Centrality is not Vitality
- Hacker News discussion
- daily.dev summary
- ACM Queue: Open Source and the Iceberg Theory
- Open Source Pledge: Burnout in Open Source
- Andrew Nesbitt: GitHub profile and blog index