{"record":{"id":"0a04b579091b9d70","repo":"affaan-m/ECC","slug":"refusing-to-replace-unowned-existing-file-desti","errorCode":null,"errorMessage":"Refusing to replace unowned existing file: ${destinationPath}","messagePattern":"Refusing to replace unowned existing file: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"scripts/lib/multi-harness-setup.js","lineNumber":244,"sourceCode":"    const conflicts = findJsonConflicts(current, operation.mergePayload);\n    if (conflicts.length > 0) {\n      throw new Error(\n        `Refusing to overwrite unowned JSON fields at ${destinationPath}: ${conflicts.join(', ')}`\n      );\n    }\n    return 'json-merge';\n  }\n  if (ownedDestinations.has(canonicalDestination)) return 'managed-update';\n  if (\n    operation.kind === 'copy-file'\n    && typeof operation.sourcePath === 'string'\n    && fs.existsSync(operation.sourcePath)\n    && fs.statSync(destinationPath).isFile()\n    && fs.readFileSync(operation.sourcePath).equals(fs.readFileSync(destinationPath))\n  ) {\n    return 'identical';\n  }\n  throw new Error(`Refusing to replace unowned existing file: ${destinationPath}`);\n}\n\nfunction writableRequirement(destinationPath) {\n  if (fs.existsSync(destinationPath)) {\n    const mode = fs.statSync(destinationPath).isDirectory()\n      ? fs.constants.W_OK | fs.constants.X_OK\n      : fs.constants.W_OK;\n    return { candidatePath: destinationPath, mode };\n  }\n\n  let candidatePath = path.dirname(destinationPath);\n  while (!fs.existsSync(candidatePath)) {\n    const parentPath = path.dirname(candidatePath);\n    if (parentPath === candidatePath) break;\n    candidatePath = parentPath;\n  }\n  return {\n    candidatePath,","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/multi-harness-setup.js#L226-L262","documentation":"Thrown by classifyManagedOperation when a destination file already exists, is not in ownedDestinations, is not a merge-json operation, and is not byte-identical to the source of a copy-file operation. ECC will not replace a pre-existing file it cannot prove it owns and cannot prove is identical to what it would write. This is the catch-all ownership guard for non-merge writes, preventing the installer from clobbering user files.","triggerScenarios":"Fires at the end of classifyManagedOperation after the create/merge/managed-update/identical branches all fail. Reached when fs.existsSync(destinationPath) is true, ownedDestinations lacks the canonical destination, operation.kind is not 'merge-json', and either operation.kind is not 'copy-file', sourcePath is missing, the destination is not a regular file, or the bytes differ from the source.","commonSituations":"A user-created file lives at a path ECC's catalog now targets; a managed file lost its install-state ownership record (state deleted/corrupt); the source file changed so a previously-identical file is now different; the destination is a directory where a file is expected; running install into a project that already has same-named files from another source.","solutions":["If you intentionally keep the file, move it aside or remove the operation from the managed profile so ECC does not target that path.","If ECC should own it, delete plan.installStatePath is NOT enough — you must either delete the destination file (so it classifies as 'create') or let ECC take ownership by establishing the state (e.g., copy the exact ECC source bytes in first so it classifies 'identical').","Verify the sourcePath bytes: if you expect 'identical' classification, ensure operation.sourcePath exists and matches the destination exactly (EOL, encoding).","Back up the existing file before deciding; ECC will not overwrite it without proof."],"exampleFix":"// before: user has /home/me/app/.claude/rules/foo.md; ECC plan copies its own foo.md there\nclassifyManagedOperation(op, owned); // throws [292]\n\n// after (option A): let ECC create it fresh\nfs.rmSync('/home/me/app/.claude/rules/foo.md'); // back up first\nclassifyManagedOperation(op, owned); // -> 'create'\n// after (option B): make bytes identical to ECC source so it classifies 'identical'\nfs.copyFileSync(op.sourcePath, '/home/me/app/.claude/rules/foo.md');","handlingStrategy":"validation","validationCode":"const fs = require('fs'); const crypto = require('crypto');\nfunction assertSafeReplace(destinationPath, operation, ownedDestinations) {\n  if (!fs.existsSync(destinationPath)) return; // 'create' is fine\n  if (ownedDestinations.has(destinationPath)) return; // 'managed-update' is fine\n  if (operation.kind === 'copy-file' && operation.sourcePath && fs.existsSync(operation.sourcePath)\n      && fs.statSync(destinationPath).isFile()\n      && fs.readFileSync(operation.sourcePath).equals(fs.readFileSync(destinationPath))) return; // 'identical'\n  throw new Error(`${destinationPath} exists, is unowned, and differs from source; back up and remove it or let ECC own it.`);\n}\nassertSafeReplace(operation.destinationPath, operation, ownedDestinations);","typeGuard":"null","tryCatchPattern":"try {\n  classifyManagedOperation(operation, ownedDestinations);\n} catch (err) {\n  if (/Refusing to replace unowned existing file/.test(err.message)) {\n    // back up the user file, remove it so install classifies 'create', then retry\n    fs.renameSync(operation.destinationPath, operation.destinationPath + '.bak');\n    classifyManagedOperation(operation, ownedDestinations);\n  } else throw err;\n}","preventionTips":["Back up and remove pre-existing files at paths ECC targets, or let ECC own them via a prior install.","For copy-file operations expecting 'identical', ensure source and destination bytes match exactly (EOL, encoding).","Do not run install into a project populated with same-named files from elsewhere without reviewing them.","If the install-state was lost, expect this guard on files ECC used to own."],"tags":["ownership","file-replace","destination-guard","kimi","safety"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}