thedotmack/claude-mem · error · Error
CLAUDE_CODE_PATH is set to
Error message
CLAUDE_CODE_PATH is set to ${describedPath} but the file does not exist. What it means
findClaudeExecutable resolves the Claude Code CLI binary. If CLAUDE_CODE_PATH is configured in ~/.claude-mem/settings.json, the library expands ~ and checks that the file exists before probing it; when the configured path does not exist on disk it throws immediately rather than falling back to PATH discovery, because an explicit setting means the user wants that exact binary.
Solutions
- Verify the path: run `ls $(node -e "console.log(require('os').homedir())")`-style check or simply `ls <configured path>` and correct CLAUDE_CODE_PATH in ~/.claude-mem/settings.json
- Remove CLAUDE_CODE_PATH from ~/.claude-mem/settings.json so the library auto-discovers `claude` on PATH
- Reinstall Claude Code CLI (`npm install -g @anthropic-ai/claude-code`) if the binary was deleted, then keep the setting pointing at the new absolute path
Example fix
// before (~/.claude-mem/settings.json)
{ "CLAUDE_CODE_PATH": "~/.local/bin/claude" } // file deleted by reinstall
// after
{ "CLAUDE_CODE_PATH": "/usr/local/bin/claude" } // verified with ls, or remove the key entirely Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'fs';
import { homedir } from 'os';
const configured = settings.CLAUDE_CODE_PATH?.trim();
if (configured) {
const p = configured.startsWith('~') ? configured.replace(/^~/, homedir()) : configured;
if (!existsSync(p)) console.warn(`CLAUDE_CODE_PATH points at missing file: ${p}`);
} Type guard
function isExistingFile(p: string | undefined): p is string {
return typeof p === 'string' && p.length > 0 && existsSync(expandTilde(p));
} Try / catch
try {
await findClaudeExecutable();
} catch (e) {
if (e.message.includes('but the file does not exist')) {
delete settings.CLAUDE_CODE_PATH; // fall back to PATH discovery
} else throw e;
} Prevention
- After editing ~/.claude-mem/settings.json, run `claude --version` at the configured path once
- Use `which claude` output (absolute path) rather than guessing install locations
- Re-check CLAUDE_CODE_PATH after upgrading or uninstalling the CLI
When it happens
Trigger: settings.CLAUDE_CODE_PATH is non-empty and expandTilde(...)/existsSync(configuredPath) returns false — the settings file points at a path that is absent (deleted binary, renamed install, wrong directory, machine migrated without the CLI).
Common situations: Hand-edited settings.json with a typo; uninstalling or upgrading Claude Code so the old absolute path (e.g. ~/.npm-global/bin/claude, ~/.local/bin/claude) disappeared; syncing dotfiles across machines where the CLI lives elsewhere.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- CLAUDE_CODE_PATH is set to
- CLAUDE_CODE_PATH is set to
- CLAUDE_MEM_SERVER_DATABASE_URL is required for `server
- Found desktop app at
- Mode file not found: .json (searched: )
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/a97fbb52785ab6fe.
Report an issue: GitHub.
Appendix: source
Thrown at src/shared/find-claude-executable.ts:364
if (cachedResolution && cachedResolution.expiresAtMs > Date.now() && _internals.existsSync(cachedResolution.path)) {
return cachedResolution.path;
}
cachedResolution = null;
const settings = _internals.loadSettings();
// --- 1. Explicit configured path ----------------------------------------
if (settings.CLAUDE_CODE_PATH) {
// A user who types `~/.local/bin/claude` in settings.json expects the shell
// convention, but nothing here runs through a shell — existsSync and
// posix_spawn take the string verbatim, so a literal `~` fails with ENOENT.
// Expand it defensively at read time so both the existence check and every
// probe spawn see a real absolute path (SettingsRoutes also normalizes on
// write; this covers files edited by hand).
const configuredPath = expandTilde(settings.CLAUDE_CODE_PATH, _internals.homedir());
const describedPath = describeConfiguredPath(settings.CLAUDE_CODE_PATH, configuredPath);
if (!_internals.existsSync(configuredPath)) {
throw new Error(
`CLAUDE_CODE_PATH is set to ${describedPath} but the file does not exist.`
);
}
const probe = probeCandidate(configuredPath);
if (probe.kind === 'capable') {
logger.info(logComponent, `Using configured CLAUDE_CODE_PATH: ${configuredPath} (${probe.version})`);
cachedResolution = {
path: configuredPath,
version: probe.version,
expiresAtMs: Date.now() + RESOLUTION_CACHE_TTL_MS,
};
return configuredPath;
}
if (probe.kind === 'incompatible') {
throw new Error(
`CLAUDE_CODE_PATH is set to ${describedPath} (${probe.version}) but that CLI is too old for claude-mem — ` +
`it rejects flags every memory agent spawn requires (${probe.detail}). ${updateInstructions()}`View on GitHub (pinned to d8bc9755e7)