affaan-m/ECC · error · Error
destination is not writable by the current user: . Fix the…
Error message
${label} destination is not writable by the current user: ${candidatePath}. Fix the project ownership or permissions, then retry. What it means
assertManagedDestinationsWritable checks with accessSync that every destination path in a managed install plan is writable (or readable as required) by the current user. When any access check fails, it throws, labeling the message 'Kimi' when the plan targets the kimi harness, otherwise 'Managed install'. It is a preflight guard so installs fail fast instead of half-completing on EACCES/ENOENT during writes.
Solutions
- Check ownership/permissions of candidatePath (ls -la) and chown or chmod so the current user has write access
- Verify you are running as the intended user (sudo down/up, wrong CI user)
- Confirm the path exists; create missing parent directories first
- Re-run the managed install after fixing permissions
Example fix
// before $ whoami; ls -ld /project/.kimi root root /project/.kimi # not writable // after $ sudo chown -R $(whoami) /project/.kimi
Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
function assertWritable(path) {
fs.accessSync(path, fs.constants.W_OK); // throws EACCES/ENOENT before install
}
// call for each plan.operations destination before preflight Try / catch
try {
await result(plan);
} catch (e) {
if (/not writable by the current user/.test(e.message)) {
console.error('Permission problem at:', e.message.match(/: ([^.]+)\./)[1]);
// prompt to chown/chmod or run under correct user
} else throw e;
} Prevention
- Run installers as the user that owns the project, not sudo
- Check permissions of config dirs (.kimi, .claude, .cursor) before scripted installs
- Avoid read-only container mounts for install destinations
When it happens
Trigger: Calling preflightManagedPlan -> assertManagedDestinationsWritable with a plan whose destinationPath does not exist, or exists but lacks the required access mode for the current user (e.g. not owner, read-only directory, root-owned path).
Common situations: Running the installer under a user that doesn't own the project directory (e.g. checked out by root or another developer); CI containers with reduced permissions; read-only volume mounts; a typo'd or non-existent destination path.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- Cannot read local asset
- ECC_MEMORY_INCOMPLETE
- Failed to create directory
- Published Nasiko binary size mismatch.
- receipt source cannot be securely read
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/63e6d801de69ddea.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/multi-harness-setup.js:335
const accessSync = dependencies.accessSync || fs.accessSync;
const destinationPaths = [
...plan.operations.map(operation => operation.destinationPath),
...(plan.installStatePath ? [plan.installStatePath] : []),
];
const requirements = new Map();
for (const destinationPath of destinationPaths) {
const requirement = writableRequirement(destinationPath);
const existingMode = requirements.get(requirement.candidatePath) || 0;
requirements.set(requirement.candidatePath, existingMode | requirement.mode);
}
for (const [candidatePath, mode] of requirements) {
try {
accessSync(candidatePath, mode);
} catch (_error) {
const label = plan.target === 'kimi' ? 'Kimi' : 'Managed install';
throw new Error(
`${label} destination is not writable by the current user: ${candidatePath}. `
+ 'Fix the project ownership or permissions, then retry.'
);
}
}
}
function preflightManagedPlan(plan, dependencies = {}) {
if (!plan || !Array.isArray(plan.operations)) {
throw new Error('A managed install plan with operations is required.');
}
if (typeof plan.installStatePath !== 'string' || plan.installStatePath.length === 0) {
throw new Error('A managed install-state path is required before preflight.');
}
const ownership = readOwnedDestinations(plan, dependencies);
const operations = plan.operations.map(operation => {
assertSafeInstallOperation(plan, operation);
return {View on GitHub (pinned to 8321021c54)