denoland/deno · error
bundle identifier {id:?} must match [A-Za-z0-9.-]+, but cont
Error message
bundle identifier {id:?} must match [A-Za-z0-9.-]+, but contains {c:?} What it means
Thrown by validate_bundle_identifier when `--identifier` contains a character outside [A-Za-z0-9.-]; the message names the offending character. Beyond Apple's CFBundleIdentifier charset this also blocks shell metacharacters, because the identifier is passed as a `codesign` argument and used as a path component of the CEF helper bundles.
Source
Thrown at cli/tools/desktop.rs:2478
/// a path component of the helper bundles.
fn validate_bundle_identifier(id: &str) -> Result<(), AnyError> {
if id.is_empty() {
bail!("bundle identifier is empty");
}
if id.len() > 155 {
// Apple's documented limit for CFBundleIdentifier on receipts is
// 155 chars; bigger values quietly truncate elsewhere in the
// toolchain.
bail!("bundle identifier {id:?} is longer than 155 characters");
}
if !id.contains('.') {
bail!(
"bundle identifier {id:?} must be in reverse-DNS form (e.g. com.acme.foo)"
);
}
for c in id.chars() {
if !(c.is_ascii_alphanumeric() || c == '.' || c == '-') {
bail!(
"bundle identifier {id:?} must match [A-Za-z0-9.-]+, but contains {c:?}",
);
}
}
if id.split('.').any(|seg| seg.is_empty()) {
bail!("bundle identifier {id:?} has an empty segment");
}
Ok(())
}
/// Walk every `.app` under `Contents/Frameworks/` and rewrite its
/// `CFBundleIdentifier` so it's a strict suffix of `main_bundle_id`.
///
/// CEF's process model: when the browser process spawns a helper for a
/// child role (gpu, renderer, plugin, …), the helper inspects its own
/// `CFBundleIdentifier` and refuses to attach to a parent whose id
/// doesn't match it as a prefix. laufey's default helper plists ship with
/// `com.example.laufey.helper.*` — which is inconsistent with whatever idView on GitHub (pinned to f7822238ca)
Solutions
- Replace invalid characters: use hyphens instead of underscores (`my-app` not `my_app`) and drop everything that is not a letter, digit, dot, or hyphen.
- Transliterate non-ASCII names to plain ASCII (Bäcker -> baeker).
- Use the reverse-DNS form of a domain you control rather than pasting a URL.
Example fix
# before deno desktop --identifier com.acme.my_app main.ts # after deno desktop --identifier com.acme.my-app main.ts
Defensive patterns
Strategy: validation
Validate before calling
# bash: enforce the charset
BUNDLE_ID="com.acme.my-app"
[[ "$BUNDLE_ID" =~ ^[A-Za-z0-9.-]+$ ]] || { echo "identifier has invalid characters" >&2; exit 1; }
deno desktop --identifier "$BUNDLE_ID" main.ts Type guard
// TypeScript
function hasOnlyBundleIdChars(id: string): boolean {
return /^[A-Za-z0-9.-]+$/.test(id);
} Prevention
- Use hyphens where you would use underscores (my-app, not my_app).
- Transliterate non-ASCII product names to ASCII before building the id.
- Add a regex lint for the identifier in CI to catch regressions early.
When it happens
Trigger: `--identifier com.acme.my_app` (underscore — the single most common hit), spaces, `://`, quotes, unicode letters (é, ü), or any shell metacharacter in the value.
Common situations: Underscores carried over from npm package names or repo names; copy-pasting a URL (`https://acme.com`) instead of the reverse-DNS form; non-ASCII company/product names pasted verbatim.
Related errors
- bundle identifier is empty
- bundle identifier {id:?} must be in reverse-DNS form (e.g. c
- Invalid deep-link scheme {scheme:?}: {reason}.
- unknown --compress format '{other}' (use xz or zstd)
- bundle identifier {id:?} is longer than 155 characters
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/23a9313f19528178.
Report an issue: GitHub.