{"record":{"id":"8626800e090ddc55","repo":"denoland/deno","slug":"cfbundleidentifier-is-empty-in","errorCode":null,"errorMessage":"CFBundleIdentifier is empty in {}","messagePattern":"CFBundleIdentifier is empty in (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/tools/desktop.rs","lineNumber":2696,"sourceCode":"  let output = std::process::Command::new(\"plutil\")\n    .arg(\"-extract\")\n    .arg(\"CFBundleIdentifier\")\n    .arg(\"raw\")\n    .arg(\"-o\")\n    .arg(\"-\")\n    .arg(&plist)\n    .output()\n    .context(\"failed to invoke plutil(1) to read CFBundleIdentifier\")?;\n  if !output.status.success() {\n    bail!(\n      \"plutil could not read CFBundleIdentifier from {}: {}\",\n      plist.display(),\n      String::from_utf8_lossy(&output.stderr).trim(),\n    );\n  }\n  let id = String::from_utf8_lossy(&output.stdout).trim().to_string();\n  if id.is_empty() {\n    bail!(\"CFBundleIdentifier is empty in {}\", plist.display());\n  }\n  Ok(id)\n}\n\n/// Cheap Mach-O sniff: a Mach-O file starts with one of the well-known\n/// magic numbers (32-bit, 64-bit, fat — both endians). Used to skip\n/// non-binaries inside `Contents/MacOS/` (shell launchers, update\n/// sentinels) before passing them to `codesign(1)`, which would reject\n/// them and abort the signing pass.\nfn is_macho_file(path: &Path) -> bool {\n  let Ok(mut f) = std::fs::File::open(path) else {\n    return false;\n  };\n  use std::io::Read;\n  let mut magic = [0u8; 4];\n  if f.read_exact(&mut magic).is_err() {\n    return false;\n  }","sourceCodeStart":2678,"sourceCodeEnd":2714,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/cli/tools/desktop.rs#L2678-L2714","documentation":"The plutil extraction succeeded (exit 0) but produced an empty string, so read_bundle_identifier rejects it. The Info.plist has a CFBundleIdentifier key whose value is empty — syntactically valid plist, semantically invalid identifier. Downstream codesigning and CEF helper prefix matching need a concrete id.","triggerScenarios":"Contents/Info.plist contains `<key>CFBundleIdentifier</key><string></string>`. plutil extracts the empty string successfully, and this explicit emptiness check fires.","commonSituations":"Templated Info.plist where the identifier placeholder was never substituted; manual plist editing that wiped the value; a generator writing the key with an unset variable.","solutions":["Set a non-empty reverse-DNS value for CFBundleIdentifier in the bundle's Contents/Info.plist, e.g. com.acme.app.","If the plist is generated during bundling, fix the upstream config that feeds the identifier so it isn't empty.","Delete the staged bundle and rebuild so the plist is regenerated from valid config."],"exampleFix":"<!-- before -->\n<key>CFBundleIdentifier</key>\n<string></string>\n\n<!-- after -->\n<key>CFBundleIdentifier</key>\n<string>com.acme.app</string>","handlingStrategy":"validation","validationCode":"id=$(plutil -extract CFBundleIdentifier raw -o - \"$APP/Contents/Info.plist\" 2>/dev/null)\n[ -n \"$id\" ] || { echo \"CFBundleIdentifier missing/empty\"; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When generating Info.plist from templates, fail the generator if the identifier substitution is empty.","Unit-test plist generation against the final artifact in CI."],"tags":["desktop","macos","plist","bundle-identifier"],"backgroundTag":"missing-bundle-identifier","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}