{"record":{"id":"35bf78dc96506749","repo":"gitbutlerapp/gitbutler","slug":"failed-to-open-paths-with-app-bundle-identifie","errorCode":null,"errorMessage":"failed to open {paths:?} with app bundle identifier '{}'","messagePattern":"failed to open (.+?) with app bundle identifier '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-api/src/open/program.rs","lineNumber":659,"sourceCode":"    }\n}\n\n#[cfg(target_os = \"macos\")]\nfn open_macos_application_via_open(\n    app: &MacosApplication,\n    paths: &NonEmpty<PathBuf>,\n) -> anyhow::Result<()> {\n    let mut cmd = Command::new(\"/usr/bin/open\");\n    cmd.arg(\"-b\").arg(&app.bundle_identifier);\n\n    for path in paths {\n        cmd.arg(path);\n    }\n\n    let status = cmd.stdout(Stdio::null()).stderr(Stdio::null()).status()?;\n\n    if !status.success() {\n        anyhow::bail!(\n            \"failed to open {paths:?} with app bundle identifier '{}'\",\n            app.bundle_identifier\n        );\n    }\n\n    Ok(())\n}\n\n/// A serializable form of [`ProgramSpec`] for user defined programs.\n#[derive(Debug, Deserialize)]\n#[serde(rename_all = \"camelCase\")]\npub struct UserDefinedProgramSpec {\n    /// Identifier used to refer to the program.\n    ///\n    /// If left empty, the ID is derived from [`Self::name`] instead.\n    pub id: Option<String>,\n    /// The display name of the program.\n    pub name: Option<String>,","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/2497b8007aa4a1922dae9a805b32ffe5b5037785/crates/but-api/src/open/program.rs#L641-L677","documentation":"Raised by open_macos_application_via_open (crates/but-api/src/open/program.rs:645), the fallback used when a macOS app has no CLI wrapper: it runs /usr/bin/open -b <bundle_identifier> <paths>. This error means the process ran but exited non-zero, which happens when no installed app registers that bundle identifier or the app cannot accept the given documents. stdout/stderr are redirected to null, so this message is the only diagnostic the caller receives.","triggerScenarios":"Opening a file with a MacosApplication whose bundle_identifier is misspelled or whose app is not installed; passing documents the target app refuses; this path is taken when resolve_cli_wrapper_abspath() fails (no CLI wrapper like 'code' exists for the app).","commonSituations":"User-defined programs with stale bundle ids after uninstall/update; Homebrew cask installs registering a different bundle id; app still quarantined on a fresh install so LaunchServices has not registered it.","solutions":["Verify the identifier is registered: mdfind \"kMDItemCFBundleIdentifier == '<bundle_id>'\" or osascript -e 'id of app \"Safari\"'.","Run /usr/bin/open -b '<bundle_id>' <one-file> manually with stderr visible to get the real exit reason.","Fix the ProgramSpec's bundle identifier or reinstall the target app.","If only certain documents fail, open them with the default handler instead."],"exampleFix":"// before: only the generic error survives\nopen_macos_application_via_open(&app, &paths)?;\n\n// after: preflight bundle-id registration\nlet out = std::process::Command::new(\"mdfind\")\n    .arg(format!(\"kMDItemCFBundleIdentifier == '{}'\", app.bundle_identifier))\n    .output()?;\nif String::from_utf8_lossy(&out.stdout).trim().is_empty() {\n    anyhow::bail!(\"no installed app registers bundle id '{}'\", app.bundle_identifier);\n}\nopen_macos_application_via_open(&app, &paths)?;","handlingStrategy":"try-catch","validationCode":"const registered = execSync(\n  `mdfind \"kMDItemCFBundleIdentifier == '${bundleId}'\"`\n).toString().trim();\nif (!registered) {\n  throw new Error(`no installed app registers bundle id '${bundleId}'`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await openWithProgram(app, paths);\n} catch (e) {\n  if (String(e.message).includes('app bundle identifier')) {\n    await openWithDefaultHandler(paths); // fallback: OS default app\n    return;\n  }\n  throw e;\n}","preventionTips":["Validate bundle ids with mdfind when the user saves a custom program.","Do not discard /usr/bin/open's stderr in wrappers — capture it for diagnostics.","Smoke-test custom programs with one representative file after every app install or update."],"tags":["macos","process","app-bundle","open-command","spawn"],"backgroundTag":"macos-open-command-failed","analyzedSha":"2497b8007aa4a1922dae9a805b32ffe5b5037785","analyzedAt":"2026-08-17T00:30:25.648Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}