discordjs/discord.js · error · Error

One or more packages have dependents that can't be released:

Error message

One or more packages have dependents that can't be released: ${unreleased.map((entry) => entry.name).join(',')}

What it means

During tree generation, packages whose dependencies have not yet been released are deferred to a later layer. If a full pass completes with no progress (releaseEntries.length === unreleased.length), the remaining packages are deadlocked: their dependents can never be released, so the algorithm throws listing the stuck packages.

Source

Thrown at packages/actions/src/releasePackages/generateReleaseTree.ts:176

				nextBranch.push(entry);
				continue;
			}

			const allDepsReleased = entry.dependsOn.every((dep) => didRelease.has(dep));
			if (allDepsReleased) {
				nextBranch.push(entry);
			} else {
				unreleased.push(entry);
			}
		}

		// Update didRelease in a second loop to avoid loop order issues
		for (const release of nextBranch) {
			didRelease.add(release.name);
		}

		if (releaseEntries.length === unreleased.length) {
			throw new Error(
				`One or more packages have dependents that can't be released: ${unreleased.map((entry) => entry.name).join(',')}`,
			);
		}

		releaseTree.push(nextBranch);
		releaseEntries = unreleased;
	}

	// Prune exclusions
	if ((!packageName || packageName === 'all') && Array.isArray(exclude) && exclude.length) {
		const neededPackages = new Set<string>();
		const excludedReleaseTree: ReleaseEntry[][] = [];

		for (const releaseBranch of releaseTree.reverse()) {
			const newThisBranch: ReleaseEntry[] = [];

			for (const entry of releaseBranch) {
				if (exclude.includes(entry.name) && !neededPackages.has(entry.name)) {

View on GitHub (pinned to a81ed8a306)

Solutions

  1. Remove the offending package from the --exclude list so its dependents can be released after it.
  2. Inspect the listed unreleased packages' dependsOn graphs for circular dependencies and break the cycle.
  3. Release the dependency packages first in a separate run, then release the dependents.
  4. Check recently changed inter-package dependencies for accidental or malformed dependsOn entries.

Example fix

// before
pnpm release all --exclude=@discordjs/builders   // node-packages depend on builders -> deadlock
// after
pnpm release all   // release dependencies in correct topological order
Defensive patterns

Strategy: validation

Validate before calling

const excluded = new Set(exclude ?? []);
for (const name of plannedNames) {
  const entry = entries.find((e) => e.name === name);
  if (entry?.dependsOn?.some((d) => excluded.has(d))) {
    throw new Error(`${name} depends on excluded package; deadlock risk`);
  }
}

Type guard

const hasExcludedDep = (entry: { dependsOn?: string[] }, excluded: Set<string>) =>
  entry.dependsOn?.some((d) => excluded.has(d)) ?? false;

Try / catch

try {
  const tree = await generateReleaseTree(dry, tag, packageName, exclude);
} catch (err) {
  if ((err as Error).message.includes("dependents that can't be released")) {
    console.error('Release graph is deadlocked; check --exclude and dependsOn cycles.');
  } else throw err;
}

Prevention

When it happens

Trigger: Building a release tree where one or more packages depend on another package that itself cannot be released (cycle in dependsOn, or a dependency excluded via --exclude that a remaining package requires), so no nextBranch can be formed and entries stop shrinking.

Common situations: Using --exclude on a package that other to-be-released packages depend on; circular dependencies between packages introduced by a refactor; malformed dependsOn metadata in a package.

Related errors


AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30). Data as JSON: /api/errors/e6919c9566bd9646. Report an issue: GitHub.