{"record":{"id":"cbb1ad590d39f24f","repo":"denoland/deno","slug":"package-name-must-not-contain-additional-path-segm","errorCode":null,"errorMessage":"package name must not contain additional path segments","messagePattern":"package name must not contain additional path segments","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/registry.rs","lineNumber":236,"sourceCode":"        .context(\"Failed to parse authorization header\")?,\n    );\n  }\n  let response = request.send().await?;\n  Ok(response)\n}\n\n/// Splits a fully qualified JSR package name (e.g. `@scope/package`) into its\n/// `(scope, package)` parts.\npub fn parse_package_name(name: &str) -> Result<(&str, &str), AnyError> {\n  // Keep the explicit path-safety checks below even if the JSR grammar changes.\n  let reference = JsrPackageReqReference::from_str(&format!(\"jsr:{name}@*\"))\n    .map_err(|_| {\n      deno_core::anyhow::anyhow!(\n        \"package name must use the '@<scope>/<package>' format\"\n      )\n    })?;\n  if reference.sub_path().is_some() {\n    bail!(\"package name must not contain additional path segments\");\n  }\n\n  let Some((scope, package)) =\n    name.strip_prefix('@').and_then(|name| name.split_once('/'))\n  else {\n    bail!(\"package name must use the '@<scope>/<package>' format\");\n  };\n  for component in [scope, package] {\n    if component == \".\" || component == \"..\" {\n      bail!(\"package name must not contain dot path segments\");\n    }\n    if component\n      .chars()\n      .any(|c| matches!(c, '/' | '\\\\' | '?' | '#' | '%'))\n    {\n      bail!(\"package name contains a URL path or delimiter character\");\n    }\n  }","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/cli/registry.rs#L218-L254","documentation":"`parse_package_name` in cli/registry.rs splits a fully qualified JSR package name (e.g. `@scope/package`) into its `(scope, package)` parts before talking to the registry API. It first parses the name as a `jsr:<name>@*` requirement reference; if that parse yields a sub-path (e.g. `@scope/pkg/extra` or `@scope/pkg@1.0.0/feature`), the name carries URL path segments beyond the package itself, which the registry publish/lookup flow does not accept, so this error is raised.","triggerScenarios":"Calling `parse_package_name` with a name containing a sub-path, e.g. `@scope/package/submodule`, `@scope/package/`, or any string that a JsrPackageReqReference parse resolves with a non-None `sub_path()`.","commonSituations":"Copy-pasting an import specifier like `jsr:@std/path/join` or a URL tail (`@scope/pkg/deep/file.ts`) into a tool flag or config field that expects only the bare package name; scripting publish automation that concatenates an export name onto the package name.","solutions":["Remove everything after the package name, keeping only `@<scope>/<package>` (e.g. `@std/path` not `@std/path/join`)","If you meant to target a specific export, pass the export/sub-path in the field designed for it (import specifier, version requirement, or CLI export argument), not in the package-name field","Strip any trailing slash or query/fragment before passing the name to the API"],"exampleFix":"// before\nparse_package_name(\"@my-scope/my-pkg/utils\")?;\n// after\nparse_package_name(\"@my-scope/my-pkg\")?;","handlingStrategy":"validation","validationCode":"fn is_bare_jsr_name(name: &str) -> bool {\n  let Some(rest) = name.strip_prefix('@') else { return false };\n  match rest.split_once('/') {\n    Some((scope, pkg)) => !scope.is_empty() && !pkg.is_empty() && !pkg.contains('/'),\n    None => false,\n  }\n}\nif !is_bare_jsr_name(user_name) {\n  eprintln!(\"pass only the bare package name, e.g. @scope/pkg\");\n  return;\n}\nlet (scope, package) = parse_package_name(user_name)?;","typeGuard":"fn is_bare_jsr_name(name: &str) -> bool {\n  name.starts_with('@')\n    && name.strip_prefix('@').and_then(|r| r.split_once('/'))\n      .map(|(s, p)| !s.is_empty() && !p.is_empty() && !p.contains('/'))\n      .unwrap_or(false)\n}","tryCatchPattern":"match parse_package_name(name) {\n  Ok((scope, package)) => /* use scope/package */,\n  Err(e) if e.to_string().contains(\"additional path segments\") => {\n    eprintln!(\"strip the sub-path: use the bare @scope/package name\");\n  }\n  Err(e) => return Err(e),\n}","preventionTips":["Never embed sub-paths or export names in package-name fields; keep them in the import/export specifier","Strip trailing slashes and query/fragment parts from user-supplied names before validating","Add a pre-call validator that rejects names with more than one '/'","Log the raw input before parsing to catch copy-paste of full import specifiers or URLs"],"tags":["jsr","package-name","validation","path"],"backgroundTag":"invalid-package-name","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-29T08:55:39.519Z","contentChangedAt":"2026-08-29T08:55:39.519Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}