thedotmack/claude-mem · warning
Failed to read existing settings file; starting fresh
Error message
Failed to read existing settings file; starting fresh
What it means
During hook bootstrap, claude-mem merges its settings into an existing settings JSON file. If the file exists but readJsonFileWithBom throws (corrupted JSON, unreadable file), this warning is logged and `existing` resets to {}. The merge then proceeds against an empty document, so the subsequent write persists only claude-mem's freshly generated keys — previously stored env, hooks, permissions, and apiKeyHelper entries are dropped.
Source
Thrown at src/services/hooks/server-bootstrap.ts:144
}
}
export function persistServerSettings(
settingsPath: string,
values: { apiKey: string; projectId: string; serverBaseUrl?: string },
): void {
const dir = dirname(settingsPath);
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
let existing: Record<string, unknown> = {};
if (existsSync(settingsPath)) {
try {
existing = readJsonFileWithBom<Record<string, unknown>>(settingsPath);
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
logger.warn('HOOK', 'Failed to read existing settings file; starting fresh', { settingsPath }, err);
existing = {};
}
}
// Settings file format: support both the flat shape (modern) and the
// env-nested shape (Claude-Code-style: { env: {...}, hooks: [...], ... }).
// `flat` is a *reference* into `existing` — the env subtree when nested, or
// the root document otherwise — so mutating `flat` mutates `existing` in
// place. We then write the full `existing` document below (NOT `flat`), so
// non-env top-level keys (hooks, permissions, apiKeyHelper, ...) survive.
// Writing `flat` back as the whole file silently dropped them (data loss).
const flat = (existing.env && typeof existing.env === 'object'
? existing.env
: existing) as Record<string, unknown>;
// Phase 1d: write the new canonical settings keys. Legacy
// `CLAUDE_MEM_SERVER_BETA_*` keys are dual-accepted by reads in
// `runtime-selector.ts`, so existing installs continue to work. Any
// legacy keys that already live in `flat` are left untouched (we don'tView on GitHub (pinned to e2d1df569a)
Solutions
- Back up the settings file immediately — after this warning the next write replaces it with only claude-mem keys.
- Run a JSON validator on the file and fix the syntax error the parse reports (the logged Error carries the position).
- Check permissions/ownership on settingsPath if the error is EACCES rather than SyntaxError.
- Restore lost hooks/permissions/env keys from a backup or dotfiles repo, then re-run the bootstrap.
Example fix
// settings.json — before (trailing comma: unparseable, prior keys get wiped)
{ "env": { "CLAUDE_MEM": "1" }, }
// after (valid JSON; existing keys survive the merge)
{ "env": { "CLAUDE_MEM": "1" } } Defensive patterns
Strategy: validation
Validate before calling
// pre-flight the settings file before any tool merges into it
import { readFileSync } from 'node:fs';
if (existsSync(settingsPath)) {
const txt = readFileSync(settingsPath, 'utf-8');
try {
JSON.parse(txt);
} catch (e) {
copyFileSync(settingsPath, `${settingsPath}.corrupt-${Date.now()}`); // preserve
throw new Error(`settings file is not valid JSON: ${settingsPath}`);
}
} Try / catch
try {
bootstrap(settingsPath);
} catch (e) {
// a warn here means prior keys were reset: restore hooks/permissions from backup
restoreFromBackup(settingsPath);
} Prevention
- Keep settings.json in a dotfiles repo or backup before upgrades.
- Never add comments or trailing commas to the settings JSON.
- Ensure only one tool writes the settings file at a time.
When it happens
Trigger: settingsPath exists and existsSync passes, but readJsonFileWithBom throws: SyntaxError from malformed or truncated JSON, EACCES on a permission-restricted file, or an encoding anomaly the reader cannot handle.
Common situations: Settings file truncated by a crash or power loss mid-write; hand-edited settings with a trailing comma or a comment; two tools writing the file concurrently; restrictive permissions after a user or home-directory migration.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- [install] Failed to parse existing settings.json, starting f
- [SETTINGS] Failed to load settings, using defaults:
- generation parse error: ${outcome.reason}
- generation job ${job.id} not found in scope
- parse_error
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/2a0f479729a75919.
Report an issue: GitHub.