{"record":{"id":"e0f27011f4968956","repo":"pnpm/pnpm","slug":"invalid-jsr-specifier","errorCode":"INVALID_JSR_SPECIFIER","errorMessage":"JSR specifier '${rawSpecifier}' is missing a package name","messagePattern":"JSR specifier '(.+?)' is missing a package name","errorType":"exception","errorClass":"PnpmError","httpStatus":null,"severity":"error","filePath":"pnpm11/resolving/jsr-specifier-parser/src/index.ts","lineNumber":43,"sourceCode":"      }\n    }\n\n    // syntax: jsr:@<scope>/<name>@<version_selector>\n    const jsrPkgName = rawSpecifier.substring(0, index)\n    return {\n      jsrPkgName,\n      npmPkgName: jsrToNpmPackageName(jsrPkgName),\n      versionSelector: rawSpecifier.substring(index + '@'.length),\n    }\n  }\n\n  // syntax: jsr:<name>@<version_selector> (invalid)\n  if (rawSpecifier.includes('@')) {\n    throw new PnpmError('MISSING_JSR_PACKAGE_SCOPE', 'Package names from JSR must have a scope')\n  }\n\n  if (!alias) {\n    throw new PnpmError('INVALID_JSR_SPECIFIER', `JSR specifier '${rawSpecifier}' is missing a package name`)\n  }\n\n  // syntax: jsr:<spec>\n  return {\n    versionSelector: rawSpecifier,\n    jsrPkgName: alias,\n    npmPkgName: jsrToNpmPackageName(alias),\n  }\n}\n\nfunction jsrToNpmPackageName (jsrPkgName: string): string {\n  if (jsrPkgName[0] !== '@') {\n    throw new PnpmError('MISSING_JSR_PACKAGE_SCOPE', 'Package names from JSR must have a scope')\n  }\n  // The returned name is used in registry URLs and metadata cache file paths,\n  // so anything that is not a valid npm package name must never make it through.\n  if (!validateNpmPackageName(jsrPkgName).validForOldPackages) {\n    throw new PnpmError('INVALID_JSR_PACKAGE_NAME', `The package name '${jsrPkgName}' is invalid`)","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/pnpm/pnpm/blob/6261b7f388016d57ca6b90340342411cd1d0d00f/pnpm11/resolving/jsr-specifier-parser/src/index.ts#L25-L61","documentation":"Thrown by parseJsrSpecifier when a `jsr:` dependency specifier carries no package name and no alias to derive one from. JSR packages are always scoped (`@scope/name`), so after stripping the `jsr:` prefix the parser needs either a leading `@scope/name` or an alias; with neither, there is nothing to resolve. The remainder of the specifier is treated as a version selector, which is why a nameless specifier is rejected rather than guessed.","triggerScenarios":"parseJsrSpecifier is invoked with a raw specifier that starts with `jsr:`, the remainder does not start with `@`, contains no `@` (so it cannot be a name@selector pair), and the optional alias argument is undefined. Concrete shapes: dependency entries like `\"foo\": \"jsr:foo\"` or `\"foo\": \"jsr:\"` where the scoped name was never typed.","commonSituations":"Hand-editing package.json and forgetting the `@scope/` part; copying a Deno-style import specifier (`jsr:foo`) into package.json; code generators or codemods that emit the protocol prefix but drop the scoped package name.","solutions":["Rewrite the dependency with the full scoped JSR name: \"@scope/pkg\": \"jsr:@scope/pkg\" (optionally with a selector: \"jsr:@scope/pkg@^1.0.0\")","Look the package up on jsr.io and copy its exact `@scope/name` verbatim","If you intended an alias install, put the scoped name in the specifier itself rather than relying on the dependency key"],"exampleFix":"// before (package.json)\n\"foo\": \"jsr:foo\"\n\n// after\n\"@scope/foo\": \"jsr:@scope/foo@^1.0.0\"","handlingStrategy":"validation","validationCode":"const JSR_SPEC = /^jsr:@[a-z0-9-]+\\/[a-z0-9-._]+(@.+)?$/\nexport function assertValidJsrDependencies (deps: Record<string, string> = {}) {\n  for (const [name, spec] of Object.entries(deps)) {\n    if (!spec.startsWith('jsr:')) continue\n    if (!JSR_SPEC.test(spec)) {\n      throw new Error(`Invalid JSR specifier \"${spec}\" for \"${name}\"; expected jsr:@scope/name[@selector]`)\n    }\n  }\n}\n// run against manifest.dependencies/devDependencies before pnpm install","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always copy JSR names from jsr.io including the @scope/ prefix","Lint package.json in CI for any jsr: specifier that lacks an @scope/name portion","Remember JSR packages surface on npm as @jsr/scope__name — never hand-write that form yourself"],"tags":["jsr","dependency-specifier","package-json","resolver"],"backgroundTag":"invalid-package-specifier","analyzedSha":"6261b7f388016d57ca6b90340342411cd1d0d00f","analyzedAt":"2026-08-17T18:30:54.750Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}