denoland/deno · error

bundle identifier {id:?} must be in reverse-DNS form (e.g. c

Error message

bundle identifier {id:?} must be in reverse-DNS form (e.g. com.acme.foo)

What it means

Thrown by validate_bundle_identifier when `--identifier` contains no dot. Apple expects a reverse-DNS form (at least one dot, like com.acme.foo); the identifier is also used for Linux .desktop filenames and Windows AppUserModelID, where the dotted form is the convention. A single bare word like `myapp` fails this check.

Source

Thrown at cli/tools/desktop.rs:2472

/// Apple's rules: ASCII alphanumerics, hyphens, and dots; must have at
/// least one dot (so it looks like reverse DNS); each dot-separated
/// segment must be non-empty and not start with a digit. We don't
/// enforce the segment-leading-letter rule strictly (some legacy apps
/// use digits) but we do reject empty segments and obvious shell
/// metacharacters — the identifier ends up as a `codesign` argument and
/// 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`.

View on GitHub (pinned to f7822238ca)

Solutions

  1. Use full reverse-DNS: `com.acme.myapp` (at least one dot required).
  2. If you have no company domain, a stable placeholder like `com.example.<appname>` or `io.github.<user>.<app>` works.
  3. Or omit `--identifier` entirely to use the synthesized `com.deno.desktop.<slug>`.

Example fix

# before
deno desktop --identifier myapp main.ts

# after
deno desktop --identifier com.acme.myapp main.ts
Defensive patterns

Strategy: validation

Validate before calling

# bash: require reverse-DNS form
BUNDLE_ID="com.acme.myapp"
[[ "$BUNDLE_ID" == *.* ]] || { echo "identifier must contain a dot" >&2; exit 1; }
deno desktop --identifier "$BUNDLE_ID" main.ts

Type guard

// TypeScript
function isReverseDnsLike(id: string): boolean {
  return id.includes(".");
}

Prevention

When it happens

Trigger: `deno desktop --identifier myapp main.ts`; `--identifier MyApp`; identifiers written in Java-package style without dots after a rename; a value like `acme:` where the dot was lost to shell quoting.

Common situations: Devs used to Electron's `name` field or Android `appId` without dots passing a bare word; config migration where `com.acme.myapp` got truncated to its last segment; quoting typos splitting the string.

Related errors


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