{"record":{"id":"779a133dd8b18315","repo":"denoland/deno","slug":"missing-name-in-config","errorCode":null,"errorMessage":"Missing name in config","messagePattern":"Missing name in config","errorType":"exception","errorClass":"AnyError","httpStatus":null,"severity":"error","filePath":"cli/tools/pack/package_json.rs","lineNumber":68,"sourceCode":"  exports: Option<serde_json::Value>,\n  // BTreeMap (not HashMap): serde_json walks BTreeMap in sorted key\n  // order, so the generated package.json — and therefore the tarball\n  // bytes — are identical across runs even with multiple deps. See the\n  // `reproducible` spec test.\n  #[serde(skip_serializing_if = \"Option::is_none\")]\n  dependencies: Option<BTreeMap<String, String>>,\n}\n\npub fn generate_package_json(\n  config_file: &ConfigFile,\n  version: &str,\n  files: &[ProcessedFile],\n) -> Result<String, AnyError> {\n  let name = config_file\n    .json\n    .name\n    .as_ref()\n    .ok_or_else(|| deno_core::anyhow::anyhow!(\"Missing name in config\"))?;\n\n  let dts_set = dts_available_set(files);\n\n  let exports = convert_exports(&config_file.json.exports, &dts_set)?;\n  let (main, types) =\n    extract_main_and_types(&config_file.json.exports, &dts_set);\n\n  // Collect dependencies from all files. BTreeMap so the serialized\n  // package.json keys come out in sorted order (reproducibility).\n  let mut dependencies: BTreeMap<String, String> = BTreeMap::new();\n\n  // Merge dependencies from all processed files\n  for file in files {\n    for (name, version) in &file.dependencies {\n      dependencies.insert(name.clone(), version.clone());\n    }\n  }\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/cli/tools/pack/package_json.rs#L50-L86","documentation":"While generating the package.json payload for the packed tarball, generate_package_json() reads `name` from deno.json to embed in the output; a config without `name` fails here before any tarball is produced. It mirrors the tarball-filename check in npm_tarball.rs — both need the same field.","triggerScenarios":"Running `deno pack` with a deno.json that lacks a `name` field, so config_file.json.name is None at cli/tools/pack/package_json.rs:68 and the generated package.json would be nameless — invalid for npm consumers.","commonSituations":"Same shape as the tarball-name error: workspace root configs holding only tasks/imports; projects created as scripts and packed later; refactoring that moved `name` into a member config.","solutions":["Add `\"name\": \"my-pkg\"` (or `\"@scope/my-pkg\"`) plus `\"version\"` to deno.json","Run pack in the workspace member that owns the publish metadata","Validate required publish fields in a pre-pack step so failures surface earlier"],"exampleFix":"// before (deno.json)\n{ \"version\": \"1.0.0\" }\n\n// after\n{ \"name\": \"@scope/my-pkg\", \"version\": \"1.0.0\" }","handlingStrategy":"validation","validationCode":"const config = JSON.parse(await Deno.readText('deno.json'));\nif (typeof config.name !== 'string' || config.name.length === 0) {\n  throw new Error('deno.json needs a \"name\" before deno pack');\n}","typeGuard":"interface NamedConfig { name: string }\nconst isNamedConfig = (c: unknown): c is NamedConfig =>\n  !!c && typeof (c as any).name === 'string' && (c as any).name.length > 0;","tryCatchPattern":null,"preventionTips":["Keep name and version in the config that owns the package","Add a config-schema check to pre-pack CI","Fail fast on missing publish fields in build scripts"],"tags":["pack","deno-json","package-json","package-name","publishing"],"backgroundTag":"missing-package-name","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}