{"record":{"id":"63e6d801de69ddea","repo":"affaan-m/ECC","slug":"label-destination-is-not-writable-by-the-curren","errorCode":null,"errorMessage":"${label} destination is not writable by the current user: ${candidatePath}. Fix the project ownership or permissions, then retry.","messagePattern":"(.+?) destination is not writable by the current user: (.+?)\\. Fix the project ownership or permissions, then retry\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/multi-harness-setup.js","lineNumber":286,"sourceCode":"  const accessSync = dependencies.accessSync || fs.accessSync;\n  const destinationPaths = [\n    ...plan.operations.map(operation => operation.destinationPath),\n    ...(plan.installStatePath ? [plan.installStatePath] : []),\n  ];\n  const requirements = new Map();\n\n  for (const destinationPath of destinationPaths) {\n    const requirement = writableRequirement(destinationPath);\n    const existingMode = requirements.get(requirement.candidatePath) || 0;\n    requirements.set(requirement.candidatePath, existingMode | requirement.mode);\n  }\n\n  for (const [candidatePath, mode] of requirements) {\n    try {\n      accessSync(candidatePath, mode);\n    } catch (_error) {\n      const label = plan.target === 'kimi' ? 'Kimi' : 'Managed install';\n      throw new Error(\n        `${label} destination is not writable by the current user: ${candidatePath}. `\n        + 'Fix the project ownership or permissions, then retry.'\n      );\n    }\n  }\n}\n\nfunction preflightManagedPlan(plan, dependencies = {}) {\n  if (!plan || !Array.isArray(plan.operations)) {\n    throw new Error('A managed install plan with operations is required.');\n  }\n  const ownership = readOwnedDestinations(plan, dependencies);\n  const operations = plan.operations.map(operation => {\n    assertSafeInstallOperation(plan, operation);\n    return {\n      destinationPath: operation.destinationPath,\n      kind: operation.kind,\n      classification: classifyManagedOperation(operation, ownership.destinations),","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/multi-harness-setup.js#L268-L304","documentation":"Thrown by assertManagedDestinationsWritable when fs.accessSync(candidatePath, mode) fails for one or more destination paths (or their nearest-existing ancestor directory). The installer verifies write (and execute, for directories) permission on every destination plus the install-state path before applying; if the current user lacks permission, the apply would fail mid-write, leaving a partial install. The label is 'Kimi' when plan.target === 'kimi', otherwise 'Managed install'.","triggerScenarios":"Fires inside assertManagedDestinationsWritable (called from preflightManagedPlan) when accessSync throws. The candidate path is either the destination itself (if it exists) or the nearest existing ancestor directory; mode is W_OK for files and W_OK|X_OK for directories. Common when files/dirs are owned by root or another user, when the project lives on a read-only mount, or when permissions were stripped.","commonSituations":"Running install with sudo such that ECC-created dirs are root-owned and a later non-root run cannot write; project on a read-only filesystem or container mount; chmod -R go-w applied to .claude; files created by a different user (CI vs local); directory without execute permission so traversal fails.","solutions":["Fix ownership of candidatePath (and the project root) so the current user owns it: sudo chown -R $USER:$USER <project>.","Restore write/execute permission: chmod -R u+w <project> and chmod u+x on directories.","If the path is on a read-only mount, move the project to a writable location or remount read-write.","Run the install as the user that owns the project rather than mixing users (avoid sudo for one run and non-sudo for the next)."],"exampleFix":"// before: .claude created by root, now running as normal user\nassertManagedDestinationsWritable(plan); // throws [293]\n\n# after: fix ownership and permissions\nsudo chown -R $USER:$USER /home/me/app\nchmod -R u+w /home/me/app\nfind /home/me/app -type d -exec chmod u+x {} \\;","handlingStrategy":"validation","validationCode":"const fs = require('fs'); const path = require('path');\nfunction writableRequirement(p) {\n  if (fs.existsSync(p)) {\n    const mode = fs.statSync(p).isDirectory() ? fs.constants.W_OK | fs.constants.X_OK : fs.constants.W_OK;\n    return { candidatePath: p, mode };\n  }\n  let c = path.dirname(p);\n  while (!fs.existsSync(c)) { const parent = path.dirname(c); if (parent === c) break; c = parent; }\n  return { candidatePath: c, mode: fs.constants.W_OK | fs.constants.X_OK };\n}\nfunction assertWritable(destinations) {\n  for (const p of destinations) {\n    const r = writableRequirement(p);\n    fs.accessSync(r.candidatePath, r.mode);\n  }\n}\nassertWritable([...plan.operations.map(o=>o.destinationPath), plan.installStatePath].filter(Boolean));","typeGuard":"null","tryCatchPattern":"try {\n  await applyMultiHarnessPlan(plan);\n} catch (err) {\n  if (/not writable by the current user/.test(err.message)) {\n    const m = err.message.match(/user: (.+)\\./);\n    throw new Error(`Fix permissions on ${m ? m[1] : 'project'} then re-run. Try: sudo chown -R $USER <project>`);\n  }\n  throw err;\n}","preventionTips":["Run ECC as the user that owns the project; avoid mixing sudo and non-sudo runs.","Ensure project dirs have u+rwx and files have u+rw before install.","Do not place the project on a read-only mount.","If a prior root-owned run created .claude, chown it back to your user first."],"tags":["permissions","filesystem","preflight","ownership","kimi"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}