thedotmack/claude-mem · warning

claude-mem: could not read

Error message

claude-mem: could not read ${USER_SETTINGS_PATH} while checking vector-search opt-out:

What it means

During install setup, userHasOptedOutOfVectorSearch reads ~/.claude/settings.json (USER_SETTINGS_PATH) to check whether the user disabled vector search. If existsSync passes but readFileSync/parseJsonWithBom throws (permissions, I/O, malformed handling), the function warns with this message and returns false — treating the user as not opted out — so install proceeds with vector search enabled by default.

Solutions

  1. Validate and repair ~/.claude/settings.json — open it, fix JSON syntax errors (jq . ~/.claude/settings.json).
  2. Fix file permissions: chown $(whoami) ~/.claude/settings.json && chmod u+rw ~/.claude/settings.json.
  3. If you actually want vector search disabled, add the opt-out to the env block of settings.json after fixing readability, then re-run install.
  4. Back up and recreate the file: mv ~/.claude/settings.json{,.bak} and let Claude regenerate defaults, then re-run install.

Example fix

// before (corrupted settings.json)
{ "env": { "CLAUDE_MEM_DISABLE_VECTOR_SEARCH": true,, } } // trailing comma
// after
$ jq . ~/.claude/settings.json   # shows the parse error, fix it
{
  "env": { "CLAUDE_MEM_DISABLE_VECTOR_SEARCH": true }
}
Defensive patterns

Strategy: validation

Validate before calling

import { accessSync, constants } from 'fs';
import { readFileSync } from 'fs';
try {
  accessSync(USER_SETTINGS_PATH, constants.R_OK);
  JSON.parse(readFileSync(USER_SETTINGS_PATH, 'utf-8')); // also catches malformed JSON
} catch (e) {
  console.warn(`Fix ~/.claude/settings.json first: ${(e as Error).message}`);
}

Type guard

function isSettingsReadError(e: unknown): e is NodeJS.ErrnoException {
  return e instanceof Error && 'code' in e && ['EACCES','EISDIR','EIO'].includes((e as NodeJS.ErrnoException).code ?? '');
}

Try / catch

try {
  raw = parseJsonWithBom(readFileSync(USER_SETTINGS_PATH, 'utf-8'));
} catch (e) {
  console.warn(`Settings unreadable (${isSettingsReadError(e) ? e.code : 'parse error'}) — defaulting vector search to enabled`);
  return false;
}

Prevention

When it happens

Trigger: readFileSync(USER_SETTINGS_PATH, 'utf-8') or parseJsonWithBom throws inside the try: EACCES on settings.json (created/modified by another user or sudo), I/O error, or a parse failure the BOM-tolerant parser cannot handle. The file exists (existsSync passed) but is unreadable/unparseable.

Common situations: settings.json corrupted by a crashed editor or manual edit (invalid JSON even after BOM handling); root-owned settings after a sudo Claude run; synced dotfiles landing read-only; encoding oddities beyond the BOM handling.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/062f5d85f8065b6d. Report an issue: GitHub.

Appendix: source

Thrown at src/npx-cli/install/setup-runtime.ts:45

    : 'Install Bun manually: `curl -fsSL https://bun.sh/install | bash` (or `brew install oven-sh/bun/bun`), then re-run `npx claude-mem install`.';
}

export function platformUvRemediation(): string {
  return IS_WINDOWS
    ? 'Install uv manually: `winget install astral-sh.uv` (or `powershell -c "irm https://astral.sh/uv/install.ps1 | iex"`), then re-run `npx claude-mem install`.'
    : 'Install uv manually: `curl -LsSf https://astral.sh/uv/install.sh | sh` (or `brew install uv`), then re-run `npx claude-mem install`.';
}

function userHasOptedOutOfVectorSearch(): boolean {
  // Read the settings file directly (the value is not in the typed defaults).
  // Honors both a top-level key and an `env`-nested key.
  let raw: unknown;
  try {
    if (!existsSync(USER_SETTINGS_PATH)) return false;
    raw = parseJsonWithBom(readFileSync(USER_SETTINGS_PATH, 'utf-8'));
  } catch (error) {
    const err = error instanceof Error ? error : new Error(String(error));
    console.warn(`claude-mem: could not read ${USER_SETTINGS_PATH} while checking vector-search opt-out:`, err);
    return false;
  }
  if (!raw || typeof raw !== 'object') return false;
  const record = raw as Record<string, unknown>;
  const envBlock = (record.env && typeof record.env === 'object')
    ? (record.env as Record<string, unknown>)
    : {};
  const value = record.CLAUDE_MEM_DISABLE_VECTOR_SEARCH ?? envBlock.CLAUDE_MEM_DISABLE_VECTOR_SEARCH;
  return value === true || value === 'true' || value === '1';
}

/**
 * Absolute paths bun's installer can write to, recomputed per call so an
 * installer that set `$BUN_INSTALL` earlier in this process is still found.
 * Honours `$BUN_INSTALL`, both `homedir()` and `%USERPROFILE%` (which differ on
 * redirected Windows profiles), `%LOCALAPPDATA%\bun`, and the platform defaults.
 * The previous `homedir()`-only list missed env-directed installs and aborted
 * with "executable not found" even when the binary was present.

View on GitHub (pinned to d8bc9755e7)