pnpm/pnpm · error · PnpmError
VERSIONING_UNRELEASABLE_PACKAGE
VERSIONING_UNRELEASABLE_PACKAGE
Error message
Change intent file ${intent.filePath} requests a ${bumpType} release of ${ref}, which cannot release (it is listed in versioning.ignore, has no version field, or has a non-semver version). Remove the entry or change it to "none". What it means
Only 'participants' — projects eligible for release — may receive version bumps. A project is not a participant when it is listed in versioning.ignore, has no version field in its manifest, or its version is not valid semver. resolveIntents throws VERSIONING_UNRELEASABLE_PACKAGE when an intent requests a real bump (anything other than none) for such a project.
Source
Thrown at pnpm11/releasing/versioning/src/assembleReleasePlan.ts:650
): Map<string, Map<string, IntentBumpType>> {
const intentBumps = new Map<string, Map<string, IntentBumpType>>()
for (const intent of intents) {
const byDir = new Map<string, IntentBumpType>()
for (const [ref, bumpType] of Object.entries(intent.releases)) {
const dirs = refs.refToDirs(ref)
if (dirs.length === 0) {
throw new PnpmError('VERSIONING_UNKNOWN_PACKAGE', `Change intent file ${intent.filePath} names ${ref}, which is not a package in this workspace`)
}
if (dirs.length > 1) {
throw new PnpmError(
'VERSIONING_AMBIGUOUS_PACKAGE',
`Change intent file ${intent.filePath} names ${ref}, which matches multiple workspace projects: ${dirs.map((dir) => `./${dir}`).join(', ')}. ` +
'Reference the project by directory instead, e.g. "./' + dirs[0] + '": ' + bumpType
)
}
const dir = dirs[0]
if (bumpType !== 'none' && !participants.has(dir)) {
throw new PnpmError(
'VERSIONING_UNRELEASABLE_PACKAGE',
`Change intent file ${intent.filePath} requests a ${bumpType} release of ${ref}, which cannot release ` +
'(it is listed in versioning.ignore, has no version field, or has a non-semver version). ' +
'Remove the entry or change it to "none".'
)
}
const existing = byDir.get(dir)
if (existing == null || (bumpType !== 'none' && BUMP_ORDER[bumpType] > (existing === 'none' ? 0 : BUMP_ORDER[existing]))) {
byDir.set(dir, bumpType)
}
}
intentBumps.set(intent.id, byDir)
}
return intentBumps
}
function assertInternalDepsUseWorkspaceProtocol (participants: Map<string, Participant>): void {
for (const participant of participants.values()) {View on GitHub (pinned to 6261b7f388)
Solutions
- Change the entry to "none" (records the change without releasing) or delete the entry from the intent file
- Remove the package from versioning.ignore in pnpm-workspace.yaml if it should actually release
- Give the package a valid semver version field in its package.json
Example fix
# .changeset/quiet-otter.md — before --- "internal-tools": patch --- Tweak script # after --- "internal-tools": none --- Tweak script
Defensive patterns
Strategy: validation
Validate before calling
import semver from 'semver'
// Check release eligibility before writing a bump for a package.
export function isReleasable (pkg: { name: string, dir: string, version?: string }, ignore: string[]): boolean {
if (ignore.includes(pkg.name) || ignore.includes(`./${pkg.dir}`)) return false
return pkg.version != null && semver.valid(pkg.version) != null
} Try / catch
try {
await assembleReleasePlan(opts)
} catch (err) {
if (err instanceof PnpmError && err.code === 'VERSIONING_UNRELEASABLE_PACKAGE') {
// Either drop the entry, set it to "none", or make the package releasable
throw new Error(`Intent targets an unreleasable package: ${err.message}`)
}
throw err
} Prevention
- Give every workspace package a valid semver version field, even private ones
- Keep versioning.ignore in sync with packages you stop releasing, and clean their pending intents
- In intent-generating tooling, filter targets through an eligibility check like the one above
When it happens
Trigger: An intent file entry with a bump type other than 'none' whose resolved directory is not in the participants map: the package is in versioning.ignore, has no version field, or its version is non-semver (e.g. '0.0.0-dev' is fine, 'next' or a git hash is not).
Common situations: Intent files written for private/internal packages that were later added to versioning.ignore; packages with a placeholder or missing version field; templates that bump every changed package.
Related errors
- VERSIONING_UNKNOWN_PACKAGE
- CATALOG_VERSION_MISMATCH
- VERSIONING_NO_PACKAGES
- WORKSPACE_ONLY
- INVALID_CHANGE_INTENT
AI-assisted analysis of pnpm/pnpm@6261b7f388 (2026-08-17).
Data as JSON: /api/errors/f076de2294a62b3d.
Report an issue: GitHub.