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't

View on GitHub (pinned to e2d1df569a)

Solutions

  1. Back up the settings file immediately — after this warning the next write replaces it with only claude-mem keys.
  2. Run a JSON validator on the file and fix the syntax error the parse reports (the logged Error carries the position).
  3. Check permissions/ownership on settingsPath if the error is EACCES rather than SyntaxError.
  4. 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

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


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/2a0f479729a75919. Report an issue: GitHub.