affaan-m/ECC · error · Error
Failed to save package manager preference: ${err.message}
Error message
Failed to save package manager preference: ${err.message} What it means
Thrown by setPreferredPackageManager when saveConfig(config) throws while writing the global preference file (~/.claude/package-manager.json via getConfigPath). The underlying write error (permission, ENOSPC, ENOENT for a missing ~/.claude, EISDIR) is wrapped with context so the caller knows the preference was validated but could not be persisted. The in-memory config is not rolled back because saveConfig is the failing step.
Source
Thrown at scripts/lib/package-manager.js:256
};
}
/**
* Set user's preferred package manager (global)
*/
function setPreferredPackageManager(pmName) {
if (!PACKAGE_MANAGERS[pmName]) {
throw new Error(`Unknown package manager: ${pmName}`);
}
const config = loadConfig() || {};
config.packageManager = pmName;
config.setAt = new Date().toISOString();
try {
saveConfig(config);
} catch (err) {
throw new Error(`Failed to save package manager preference: ${err.message}`);
}
return config;
}
/**
* Set project's preferred package manager
*/
function setProjectPackageManager(pmName, projectDir = process.cwd()) {
if (!PACKAGE_MANAGERS[pmName]) {
throw new Error(`Unknown package manager: ${pmName}`);
}
const configDir = path.join(projectDir, '.claude');
const configPath = path.join(configDir, 'package-manager.json');
const config = {
packageManager: pmName,View on GitHub (pinned to 01e15490f0)
Solutions
- Create ~/.claude and ensure it is writable: mkdir -p ~/.claude && chown -R $USER ~/.claude.
- Verify HOME is set and writable: echo $HOME and touch "$HOME/.claude/test".
- Free disk space if ENOSPC; remove the path if it is a directory/file conflict (EISDIR/EEXIST).
- Run the tool as the user that owns HOME rather than a restricted service account.
Example fix
# before: ~/.claude missing or owned by root
setPreferredPackageManager('pnpm'); // throws [297]
# after: ensure writable config dir
mkdir -p ~/.claude
sudo chown -R "$USER:$USER" ~/.claude
# then re-run
setPreferredPackageManager('pnpm'); Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require('fs'); const path = require('path');
function assertGlobalConfigWritable() {
const { getClaudeDir } = require('./scripts/lib/utils');
const dir = getClaudeDir();
fs.mkdirSync(dir, { recursive: true });
const probe = path.join(dir, '.ecc-write-probe');
fs.writeFileSync(probe, ''); fs.unlinkSync(probe);
}
assertGlobalConfigWritable();
setPreferredPackageManager('pnpm'); Type guard
null
Try / catch
try {
setPreferredPackageManager(pmName);
} catch (err) {
if (/Failed to save package manager preference/.test(err.message)) {
// ensure ~/.claude exists and is writable, then retry once
fs.mkdirSync(path.join(os.homedir(), '.claude'), { recursive: true });
setPreferredPackageManager(pmName);
} else throw err;
} Prevention
- Ensure ~/.claude exists and is owned by the current user before first run.
- Verify HOME is set and writable in containers/CI.
- Free disk space if writes start failing with ENOSPC.
- Run ECC as the user that owns HOME, not as a service account without a real home.
When it happens
Trigger: Fires in the catch of saveConfig inside setPreferredPackageManager. Occurs when writeFile to getConfigPath() fails: ~/.claude does not exist, the path is not writable by the current user, the disk is full, the path resolves to a directory, or a read-only HOME (container/sandbox).
Common situations: First run on a system where ~/.claude was never created and utils.writeFile does not mkdir; HOME points to a read-only or non-existent dir; running as a user without write access to HOME; disk full; ~/.claude accidentally turned into a regular file or owned by root.
Related errors
- Failed to save package manager config to ${configPath}: ${er
- ${label} destination is not writable by the current user: ${
- Unknown package manager: ${pmName}
- Failed to create directory '${dirPath}': ${err.message}
- Multiple ECC repo roots detected: ${uniqueRepoRoots.join(',
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/da0409b431590f21.
Report an issue: GitHub.