pnpm/pnpm · error · PnpmError
VERSIONING_INVALID_LANE_NAME
VERSIONING_INVALID_LANE_NAME
Error message
Invalid lane name: ${laneName}. "main" is the reserved default lane; spell it in lowercase to move packages back onto it. What it means
Thrown by `pnpm lane <name>` when the name is a case variant of the reserved default lane — `Main`, `MAIN`, etc. — rather than the exact lowercase `main`. `main` is not a stored lane; it means "move back onto the stable release track", so a near-identical casing would create a real lane that shadows the reserved one.
Source
Thrown at pnpm11/releasing/commands/src/lane/index.ts:110
for (const [key, lane] of Object.entries(lanes)) {
for (const dir of refs.refToDirs(key)) {
laneByDir.set(dir, { key, lane })
}
}
let output: string
if (laneName === MAIN_LANE) {
for (const project of selected) {
const existing = laneByDir.get(project.dir)
if (existing != null) {
delete lanes[existing.key]
}
}
output = `Moved to the main lane:\n${selected.map((project) => ` ${refFor(project, refs)}\n`).join('')}` +
'The accumulated stable versions release on the next "pnpm version -r" run.'
} else {
if (laneName.toLowerCase() === MAIN_LANE) {
throw new PnpmError('VERSIONING_INVALID_LANE_NAME', `Invalid lane name: ${laneName}. "main" is the reserved default lane; spell it in lowercase to move packages back onto it.`)
}
// A purely numeric lane name is rejected because semver parses an
// all-digit prerelease identifier as a number, which changes sorting
// semantics.
if (!/^[0-9A-Z-]+$/i.test(laneName) || /^\d+$/.test(laneName)) {
throw new PnpmError('VERSIONING_INVALID_LANE_NAME', `Invalid lane name: ${laneName}. Lane names may contain only alphanumerics and hyphens, and cannot be purely numeric.`)
}
for (const project of selected) {
const existing = laneByDir.get(project.dir)
if (existing != null && existing.lane !== laneName) {
throw new PnpmError('VERSIONING_ALREADY_ON_LANE', `${refFor(project, refs)} is already on the "${existing.lane}" lane. Move it back with "pnpm lane main" first.`)
}
if (existing == null) {
lanes[refFor(project, refs)] = laneName
}
}
output = `Moved to the "${laneName}" lane:\n${selected.map((project) => ` ${refFor(project, refs)}\n`).join('')}`
}View on GitHub (pinned to 6261b7f388)
Solutions
- Spell it lowercase: `pnpm lane main --filter <pkg>...`
- For a genuine separate lane, pick a name that is not a case variant of `main`
Example fix
# before pnpm lane Main --filter @acme/napi... # after pnpm lane main --filter @acme/napi...
Defensive patterns
Strategy: type-guard
Type guard
const MAIN_LANE = 'main' const isAcceptableLaneName = (name) => name === MAIN_LANE || name.toLowerCase() !== MAIN_LANE
Prevention
- Lowercase all lane names in scripts (`main`, `alpha`, `rc`)
- Validate lane names in release tooling before shelling out to `pnpm lane`
When it happens
Trigger: Any invocation where `laneName.toLowerCase() === 'main'` but `laneName !== 'main'`: `pnpm lane Main --filter <pkg>...`, `pnpm lane MAIN ...`.
Common situations: Capitalizing commands out of habit or autocorrect; scripting with a variable that got title-cased.
Related errors
- WORKSPACE_ONLY
- VERSIONING_LANE_FILTER_REQUIRED
- VERSIONING_NO_PACKAGES
- VERSIONING_ALREADY_ON_LANE
- CONFIG_SET_UNSUPPORTED_WORKSPACE_KEY
AI-assisted analysis of pnpm/pnpm@6261b7f388 (2026-08-17).
Data as JSON: /api/errors/d70a4a35b15dc236.
Report an issue: GitHub.