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
- Validate and repair ~/.claude/settings.json — open it, fix JSON syntax errors (jq . ~/.claude/settings.json).
- Fix file permissions: chown $(whoami) ~/.claude/settings.json && chmod u+rw ~/.claude/settings.json.
- 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.
- 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
- Validate settings.json with jq or a JSON linter after every manual edit.
- Never run Claude Code with sudo — it leaves root-owned settings.json behind.
- Back up settings.json before editing; restore on parse failures.
- Remember a failed opt-out check silently enables vector search — verify after install if you rely on the opt-out.
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
- Corrupt JSON in , refusing to overwrite user hooks
- Corrupt JSON in , refusing to overwrite user settings
- Failed to read existing settings file; starting fresh
- [install] Failed to parse existing settings.json, starting…
- [install] Failed to read existing plugin version:
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)