{"record":{"id":"85bccb767f8f155f","repo":"Hmbown/CodeWhale","slug":"the-installation-destination-contains-a-different","errorCode":null,"errorMessage":"The installation destination contains a different application.","messagePattern":"The installation destination contains a different application\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/app/install-macos.mjs","lineNumber":10,"sourceCode":"import fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { spawnSync } from \"node:child_process\";\n\n/** Publish a verified bundle in one rename, retaining the previous install. */\nexport function replaceMacBundle(source, destination, { prepare = () => {}, verify = verifySignature } = {}) {\n  const parent = path.dirname(destination);\n  fs.mkdirSync(parent, { recursive: true });\n  if (fs.existsSync(destination) && !fs.existsSync(path.join(destination, \"Contents\", \"Resources\", \"plugin\", \"app\", \"daemon.mjs\"))) throw new Error(\"The installation destination contains a different application.\");\n  if (fs.existsSync(destination) && fs.lstatSync(destination).isSymbolicLink()) throw new Error(\"The installation destination must not be a symlink.\");\n  const staging = fs.mkdtempSync(path.join(parent, \".codewhale-cu-update-\"));\n  const next = path.join(staging, path.basename(destination));\n  let backup = null;\n  try {\n    fs.cpSync(source, next, { recursive: true });\n    prepare(next);\n    verify(next);\n    if (fs.existsSync(destination)) {\n      const backups = path.join(parent, \".codewhale-cu-backups\");\n      fs.mkdirSync(backups, { recursive: true, mode: 0o700 });\n      backup = path.join(backups, `${Date.now()}-${crypto.randomUUID()}.app`);\n      fs.renameSync(destination, backup);\n    }\n    try { fs.renameSync(next, destination); }\n    catch (error) { if (backup) fs.renameSync(backup, destination); throw error; }\n    return { backup };\n  } finally { fs.rmSync(staging, { recursive: true, force: true }); }","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/app/install-macos.mjs#L1-L28","documentation":"replaceMacBundle refuses to overwrite an existing destination bundle unless it looks like this app's bundle (it must contain Contents/Resources/plugin/app/daemon.mjs). This guards against clobbering an unrelated .app the user placed at the same path, which would destroy another application's data.","triggerScenarios":"Calling replaceMacBundle(source, destination) where destination exists but lacks the daemon.mjs marker file — i.e. a different .app bundle, a plain directory, or a bundle from a differently-structured app sits at the install path.","commonSituations":"Install destination changed to a path that already hosts another app (e.g. a name collision under /Applications); an old install layout predating the plugin/app directory structure; a partially deleted bundle missing its resources.","solutions":["Remove or move the unrelated item at destination, or point destination at a free path","Verify the destination is the correct install location and contains the expected daemon.mjs marker if it should be this app","If it is a stale install of this app, reinstall cleanly from scratch rather than replacing","Confirm bundle layout matches the current app structure (Contents/Resources/plugin/app/daemon.mjs)"],"exampleFix":"// before\ncode.replaceMacBundle(stagedBundle, \"/Applications/SomeOther.app\");\n// after\ncode.replaceMacBundle(stagedBundle, \"/Applications/Codewhale Computer Use.app\");","handlingStrategy":"validation","validationCode":"const marker = path.join(destination, \"Contents\", \"Resources\", \"plugin\", \"app\", \"daemon.mjs\");\nif (fs.existsSync(destination) && !fs.existsSync(marker)) {\n  throw new Error(\"destination holds a different app\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  replaceMacBundle(src, dest);\n} catch (e) {\n  if (e.message.includes(\"different application\")) {\n    promptUser(`Move the existing app at ${dest} before installing.`);\n  } else throw e;\n}","preventionTips":["Use a dedicated, app-specific install path to avoid collisions","Check destination contents before every update","Never point the installer at generic paths without a fixed app name","Detect foreign bundles early and surface a user-facing move/rename prompt"],"tags":["install","macos","safety-guard","bundle"],"backgroundTag":"file-already-exists","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}