thedotmack/claude-mem · error
[SETTINGS] Failed to auto-migrate settings file:
Error message
[SETTINGS] Failed to auto-migrate settings file:
What it means
Not a thrown exception but a swallowed warning logged in loadFromFile when the automatic schema migration fails. When a legacy settings file has the shape { env: {...} } with no peer root keys, the loader flattens it in memory and then attempts writeJsonFileAtomic(settingsPath, flatSettings) to persist the new flat schema. This warning fires when that atomic write fails — typically due to filesystem permission errors, a read-only data directory, ENOSPC, EACCES/EPERM on the settings file, or a disk I/O failure. The migration itself still succeeds in memory, so settings load proceeds with defaults merged; the file just remains in the legacy nested format and will be re-migrated on every load.
Source
Thrown at src/shared/SettingsDefaultsManager.ts:332
const settingsData = readFileSync(settingsPath, 'utf-8');
const settings = parseJsonWithBom<Record<string, any>>(settingsData);
let flatSettings = settings;
const hasNestedEnv = settings.env && typeof settings.env === 'object' && !Array.isArray(settings.env);
const hasPeerRootKeys = hasNestedEnv && Object.keys(settings).some((key) => key !== 'env');
if (hasNestedEnv) {
flatSettings = settings.env;
// A legacy file containing only `{ env: {...} }` can be flattened
// safely. If it also contains peer root keys (hooks, permissions,
// theme, etc.), retain the wrapper: flattening would destroy user data.
if (!hasPeerRootKeys) {
try {
writeJsonFileAtomic(settingsPath, flatSettings);
// stderr, never stdout — same JSON-on-stdout contract as above.
console.warn('[SETTINGS] Migrated settings file from nested to flat schema:', settingsPath);
} catch (error: unknown) {
console.warn('[SETTINGS] Failed to auto-migrate settings file:', settingsPath, error instanceof Error ? error.message : String(error));
// Continue with in-memory migration even if write fails
}
}
}
if (flatSettings.CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES === LEGACY_TELEGRAM_TRIGGER_TYPES) {
flatSettings = {
...flatSettings,
CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES: this.DEFAULTS.CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES,
};
try {
writeJsonFileAtomic(
settingsPath,
hasPeerRootKeys ? { ...settings, env: flatSettings } : flatSettings,
);
// stderr, never stdout — same JSON-on-stdout contract as above.
console.warn('[SETTINGS] Migrated Telegram trigger types off the legacy default:', settingsPath);View on GitHub (pinned to 8bc631a71a)
Solutions
- Check filesystem permissions on the settings file and its parent directory; ensure the process user has write access (chmod/chown the file or directory).
- Free disk space if the error message contains ENOSPC, since a full disk prevents the atomic write.
- Verify the settings file is not read-only or locked by another process; close editors or tools holding the file and retry.
- If the directory is intentionally read-only, accept the warning: settings still load correctly in memory, or move the data dir to a writable location.
- Manually rewrite the settings file in the flat schema (move the contents of the env object to the top level) so the auto-migration is no longer needed.
- If the error persists, replace the settings file by deleting it so a fresh file with defaults is created on next load, then reapply custom settings.
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at src/shared/SettingsDefaultsManager.ts:259 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-09-09).
Data as JSON: /api/errors/ef954d5edef596b6.
Report an issue: GitHub.