denoland/deno · error

macos.codesignIdentity is empty

Error message

macos.codesignIdentity is empty

What it means

After the macOS-host check, codesign_macos_bundle rejects an empty signing identity string. The macos.codesignIdentity key is present in deno.json but its value is "" — an identity that cannot exist, and passing it to codesign(1) would only fail later with a more confusing error.

Source

Thrown at cli/tools/desktop.rs:2600

/// Re-uses the JIT entitlements that ship with the laufey CEF bundle
/// (`Contents/Frameworks/<helper>.app/Contents/Resources/...entitlements...`
/// or, more robustly, the per-helper entitlements laufey bundles next to
/// each helper). When entitlements aren't present we fall back to
/// signing without them — the binary will still launch but V8 won't
/// get JIT permission.
fn codesign_macos_bundle(
  app_bundle: &Path,
  identity: &str,
) -> Result<(), AnyError> {
  if !cfg!(target_os = "macos") {
    bail!(
      "codesigning requires a macOS build host (uses `codesign(1)`). \
       Run `deno desktop` on macOS, or drop `macos.codesignIdentity` \
       from your deno.json when cross-building."
    );
  }
  if identity.is_empty() {
    bail!("macos.codesignIdentity is empty");
  }
  log::info!(
    "{} bundle with identity {:?}",
    colors::green("Codesigning"),
    identity,
  );

  // Read the bundle id from the main Info.plist so we can override the
  // signed identifier on `Contents/MacOS/laufey`. The default identifier
  // codesign infers from a bare Mach-O binary is `laufey` (the basename),
  // which doesn't match the .app's CFBundleIdentifier — and UN refuses
  // notification authorization when the running binary's signed id
  // doesn't match the bundle's id. Forcing `--identifier=<bundle_id>`
  // makes them match.
  let bundle_id = read_bundle_identifier(app_bundle)?;

  // Sign helpers first (inside → outside). The order within helpers
  // doesn't matter — they don't nest into each other.

View on GitHub (pinned to f7822238ca)

Solutions

  1. Set a real identity, e.g. "Apple Development: dev@acme.com (ABCD1234)" or "Developer ID Application: ACME Inc (TEAMID)".
  2. If you don't intend to sign, delete the macos.codesignIdentity key entirely instead of leaving it empty.
  3. For unsigned local testing, ad-hoc signing with identity "-" is a non-empty value codesign accepts.

Example fix

// before
"macos": { "codesignIdentity": "" }

// after (real identity)
"macos": { "codesignIdentity": "Developer ID Application: ACME Inc (TEAMID)" }
// or remove the key entirely to skip signing
Defensive patterns

Strategy: validation

Validate before calling

const identity = config.desktop?.macos?.codesignIdentity;
if (identity !== undefined && identity.trim() === "") {
  throw new Error("macos.codesignIdentity must be a real identity or absent");
}

Type guard

function isValidIdentity(v: unknown): v is string {
  return typeof v === "string" && v.trim().length > 0;
}

Prevention

When it happens

Trigger: deno.json contains "macos": { "codesignIdentity": "" } — typically from a template placeholder never filled in, or from env-var interpolation ("codesignIdentity": "$SIGN_ID") where the variable is unset and yields an empty string.

Common situations: Scaffolded desktop projects with placeholder config; CI where the secrets-to-config mapping produced an empty value; local testing where someone enabled the key 'to be filled later'.

Related errors


AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20). Data as JSON: /api/errors/4731be03c1c73f1f. Report an issue: GitHub.