thedotmack/claude-mem · error · Error
CLAUDE_CODE_PATH is set to
Error message
CLAUDE_CODE_PATH is set to "${settings.CLAUDE_CODE_PATH}" but the file does not exist. What it means
find-claude-executable's first resolution stage: settings.CLAUDE_CODE_PATH is set (tilde-expanded defensively, since existsSync and posix_spawn take the string verbatim) but the file does not exist, so resolution aborts before probing any discovered candidates. An explicitly configured path is authoritative — a bad value is an error, not a hint to silently fall back to PATH search.
Solutions
- Point CLAUDE_CODE_PATH at the real binary location (check `which claude` or `command -v claude`).
- If the CLI is gone, reinstall it (npm install -g @anthropic-ai/claude-code) or remove CLAUDE_CODE_PATH entirely so PATH discovery takes over.
- Verify the path with ls after tilde expansion; remember no shell runs here, so env vars like $HOME inside the value are not expanded.
Example fix
// settings.json before
{ "CLAUDE_CODE_PATH": "~/.local/bin/claude-v1" }
// after
{ "CLAUDE_CODE_PATH": "~/.local/bin/claude" } Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'fs';
import { expandTilde } from './tilde.js';
const configured = settings.CLAUDE_CODE_PATH;
if (configured && !existsSync(expandTilde(configured, os.homedir()))) {
throw new Error(`CLAUDE_CODE_PATH is stale: ${configured} — run \`which claude\` and update settings.json`);
} Prevention
- After moving or upgrading your CLI, re-check settings.json's CLAUDE_CODE_PATH with ls.
- Prefer unsetting CLAUDE_CODE_PATH and relying on PATH discovery unless you truly need a pin.
- Remember no shell expands the value: use absolute paths or a leading ~ only.
When it happens
Trigger: settings.json contains a stale path after the CLI was moved, upgraded via a different package manager, or uninstalled; a typo in the path; the file lives on a mount that is not mounted (network drive, encrypted home not unlocked); literal '~' in a config edited outside SettingsRoutes (handled) mixed with other expansions that are not.
Common situations: Switching between nvm/brew/npm installs that relocate the claude binary; dotfiles synced to a new machine where the path differs; containers where the configured path belongs to the host, not the image.
Related errors
- CLAUDE_CODE_PATH is set to
- CLAUDE_CODE_PATH is set to
- Found desktop app at
- Anthropic API rejected request with HTTP 400: this model…
- auth_invalid
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/d9429303ef5940ab.
Report an issue: GitHub.
Appendix: source
Thrown at src/shared/find-claude-executable.ts:295
export function findClaudeExecutable(logComponent: Component = 'SDK'): string {
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());
if (!_internals.existsSync(configuredPath)) {
throw new Error(
`CLAUDE_CODE_PATH is set to "${settings.CLAUDE_CODE_PATH}" 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 "${settings.CLAUDE_CODE_PATH}" (${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 e2d1df569a)