{"record":{"id":"5426ab7356a8f2a5","repo":"pnpm/pnpm","slug":"invalid-node-release-channel","errorCode":"INVALID_NODE_RELEASE_CHANNEL","errorMessage":"\"${releaseChannel}\" is not a valid Node.js release channel","messagePattern":"\"(.+?)\" is not a valid Node\\.js release channel","errorType":"exception","errorClass":"PnpmError","httpStatus":null,"severity":"error","filePath":"pnpm11/engine/runtime/node-resolver/src/parseNodeSpecifier.ts","lineNumber":17,"sourceCode":"import { PnpmError } from '@pnpm/error'\n\nexport interface NodeSpecifier {\n  releaseChannel: string\n  versionSpecifier: string\n}\n\nconst RELEASE_CHANNELS = ['nightly', 'rc', 'test', 'v8-canary', 'release']\n\nconst isStableVersion = (version: string): boolean => /^\\d+\\.\\d+\\.\\d+$/.test(version)\n\nexport function parseNodeSpecifier (specifier: string): NodeSpecifier {\n  // Handle \"channel/version\" format: \"rc/18\", \"rc/18.0.0-rc.4\", \"release/22.0.0\", \"nightly/latest\"\n  if (specifier.includes('/')) {\n    const [releaseChannel, versionSpecifier] = specifier.split('/', 2)\n    if (!RELEASE_CHANNELS.includes(releaseChannel)) {\n      throw new PnpmError('INVALID_NODE_RELEASE_CHANNEL', `\"${releaseChannel}\" is not a valid Node.js release channel`, {\n        hint: `Valid release channels are: ${RELEASE_CHANNELS.join(', ')}`,\n      })\n    }\n    return { releaseChannel, versionSpecifier }\n  }\n\n  // Exact prerelease version with a recognized release channel suffix.\n  // e.g. \"22.0.0-rc.4\", \"22.0.0-nightly20250315d765e70802\", \"22.0.0-v8-canary2025...\"\n  const prereleaseChannelMatch = specifier.match(/^\\d+\\.\\d+\\.\\d+-(nightly|rc|test|v8-canary)/)\n  if (prereleaseChannelMatch != null) {\n    return { releaseChannel: prereleaseChannelMatch[1], versionSpecifier: specifier }\n  }\n\n  // Exact stable version: \"22.0.0\"\n  if (isStableVersion(specifier)) {\n    return { releaseChannel: 'release', versionSpecifier: specifier }\n  }\n","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/pnpm/pnpm/blob/5b11d3a15b9022a2109cb18ed96a5d652630371f/pnpm11/engine/runtime/node-resolver/src/parseNodeSpecifier.ts#L1-L35","documentation":"Thrown by parseNodeSpecifier when a runtime:node specifier uses the 'channel/version' form but the channel token is not one of nightly, rc, test, v8-canary, or release. The hint lists the valid channels. This is pure input validation before any network access.","triggerScenarios":"Specifiers like runtime:stable/22, runtime:beta/20, or runtime:lts/18 — anything with a slash whose first segment is not in RELEASE_CHANNELS. Commonly from guessing channel names that nodejs.org does not use.","commonSituations":"Assuming 'lts' or 'stable' or 'current' are channels (they are not in this API — LTS is a version range, stable is the default 'release' channel); typos like 'canary' instead of 'v8-canary'.","solutions":["Use a valid channel: nightly, rc, test, v8-canary, or release","For LTS, just use a semver range covering the LTS line (e.g. runtime:20.x) with no channel prefix","For stable releases, omit the channel entirely — runtime:22 is already the release channel"],"exampleFix":"// before\n\"node\": \"runtime:stable/22.0.0\"\n// after\n\"node\": \"runtime:release/22.0.0\"\n// or simply\n\"node\": \"runtime:22.0.0\"","handlingStrategy":"type-guard","validationCode":"const RELEASE_CHANNELS = ['nightly', 'rc', 'test', 'v8-canary', 'release']\nfunction assertValidChannel (spec: string): void {\n  const channel = spec.includes('/') ? spec.split('/')[0] : null\n  if (channel != null && !RELEASE_CHANNELS.includes(channel)) {\n    throw new Error(`Invalid channel '${channel}'. Valid: ${RELEASE_CHANNELS.join(', ')}`)\n  }\n}","typeGuard":"const isValidNodeChannel = (channel: string): boolean =>\n  ['nightly', 'rc', 'test', 'v8-canary', 'release'].includes(channel)","tryCatchPattern":"try {\n  await install()\n} catch (err) {\n  if (err instanceof PnpmError && err.code === 'INVALID_NODE_RELEASE_CHANNEL') {\n    // the hint already lists valid channels — drop the invalid prefix or use 'release'\n  }\n  throw err\n}","preventionTips":["Remember there is no 'lts'/'stable' channel — use a semver range or 'release'","Lint package.json for runtime: specifiers with a channel whitelist","Use 'v8-canary' (not 'canary') for V8 canary builds"],"tags":["nodejs","validation","specifier","release-channel"],"backgroundTag":null,"analyzedSha":"5b11d3a15b9022a2109cb18ed96a5d652630371f","analyzedAt":"2026-08-16T13:18:59.198Z","schemaVersion":2},"datasetVersion":"2026-08-16T18:17:16.020Z"}