{"record":{"id":"ea0425e3fafd738b","repo":"denoland/deno","slug":"missing-name","errorCode":null,"errorMessage":"Missing name","messagePattern":"Missing name","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/tools/pack/npm_tarball.rs","lineNumber":27,"sourceCode":"\nuse super::AssetFile;\nuse super::ProcessedFile;\nuse super::ReadmeOrLicense;\nuse super::extensions::js_to_dts_extension;\n\n/// Compute the default tarball filename (`scope-name-version.tgz`) that\n/// `pack` writes when no `--output` is given. Extracted so the asset\n/// collector can exclude this exact path (instead of guessing by `.tgz`\n/// extension) and so the name is computed in exactly one place.\npub fn default_tarball_filename(\n  config_file: &ConfigFile,\n  version: &str,\n) -> Result<PathBuf, AnyError> {\n  let name = config_file\n    .json\n    .name\n    .as_ref()\n    .ok_or_else(|| deno_core::anyhow::anyhow!(\"Missing name\"))?;\n  // Convert @scope/name to scope-name\n  let normalized = name.replace('@', \"\").replace('/', \"-\");\n  // The package name shape is checked against `@scope/name` higher up\n  // (see `pack` in mod.rs), but that check is loose — it does not\n  // forbid path-traversal sequences. Treat this as a hard safety\n  // boundary right before we open a file, rejecting any derived\n  // tarball name that contains `..` or path separators so we never\n  // escape the cwd regardless of upstream validation drift.\n  if normalized.contains(\"..\") || normalized.contains('/') {\n    return Err(deno_core::anyhow::anyhow!(\n      \"refusing to write tarball with unsafe name derived from package: {}\",\n      name\n    ));\n  }\n  Ok(PathBuf::from(format!(\"{}-{}.tgz\", normalized, version)))\n}\n\n/// Tar archive paths must use forward slashes, even on Windows. Output paths","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/cli/tools/pack/npm_tarball.rs#L9-L45","documentation":"`deno pack` computes the default tarball filename (name-version.tgz) from the package name in deno.json. If the config has no \"name\" field there is nothing to derive a filename from, so the command aborts before writing anything.","triggerScenarios":"Running `deno pack` without --output in a workspace whose deno.json (or the relevant member config) omits \"name\".","commonSituations":"deno.json used purely as a task/import map without package identity; multi-member workspaces where pack targets an unnamed member.","solutions":["Add a valid \"name\" to deno.json (e.g. \"@scope/pkg\" or \"pkg\")","Or bypass the default name: deno pack --output out.tgz","In workspaces, ensure the member's own deno.json carries the name"],"exampleFix":"// deno.json before\n{ \"tasks\": { \"pack\": \"deno pack\" } }\n// after\n{ \"name\": \"@scope/pkg\", \"tasks\": { \"pack\": \"deno pack\" } }","handlingStrategy":"validation","validationCode":"# fail fast when the packable config lacks identity\ngrep -q '\"name\"' deno.json || { echo 'deno.json is missing \"name\" — required by deno pack' >&2; exit 2; }\ndeno pack","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat name+version as required fields for any packable package","Wire the preflight check into the pack task itself"],"tags":["pack","config","deno-json","npm"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}