{"record":{"id":"d9429303ef5940ab","repo":"thedotmack/claude-mem","slug":"claude-code-path-is-set-to-settings-claude-code","errorCode":null,"errorMessage":"CLAUDE_CODE_PATH is set to \"${settings.CLAUDE_CODE_PATH}\" but the file does not exist.","messagePattern":"CLAUDE_CODE_PATH is set to \"(.+?)\" but the file does not exist\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/shared/find-claude-executable.ts","lineNumber":295,"sourceCode":"export function findClaudeExecutable(logComponent: Component = 'SDK'): string {\n  if (cachedResolution && cachedResolution.expiresAtMs > Date.now() && _internals.existsSync(cachedResolution.path)) {\n    return cachedResolution.path;\n  }\n  cachedResolution = null;\n\n  const settings = _internals.loadSettings();\n\n  // --- 1. Explicit configured path ----------------------------------------\n  if (settings.CLAUDE_CODE_PATH) {\n    // A user who types `~/.local/bin/claude` in settings.json expects the shell\n    // convention, but nothing here runs through a shell — existsSync and\n    // posix_spawn take the string verbatim, so a literal `~` fails with ENOENT.\n    // Expand it defensively at read time so both the existence check and every\n    // probe spawn see a real absolute path (SettingsRoutes also normalizes on\n    // write; this covers files edited by hand).\n    const configuredPath = expandTilde(settings.CLAUDE_CODE_PATH, _internals.homedir());\n    if (!_internals.existsSync(configuredPath)) {\n      throw new Error(\n        `CLAUDE_CODE_PATH is set to \"${settings.CLAUDE_CODE_PATH}\" but the file does not exist.`\n      );\n    }\n\n    const probe = probeCandidate(configuredPath);\n    if (probe.kind === 'capable') {\n      logger.info(logComponent, `Using configured CLAUDE_CODE_PATH: ${configuredPath} (${probe.version})`);\n      cachedResolution = {\n        path: configuredPath,\n        version: probe.version,\n        expiresAtMs: Date.now() + RESOLUTION_CACHE_TTL_MS,\n      };\n      return configuredPath;\n    }\n    if (probe.kind === 'incompatible') {\n      throw new Error(\n        `CLAUDE_CODE_PATH is set to \"${settings.CLAUDE_CODE_PATH}\" (${probe.version}) but that CLI is too old for claude-mem — ` +\n        `it rejects flags every memory agent spawn requires (${probe.detail}). ${updateInstructions()}`","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/shared/find-claude-executable.ts#L277-L313","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// settings.json before\n{ \"CLAUDE_CODE_PATH\": \"~/.local/bin/claude-v1\" }\n\n// after\n{ \"CLAUDE_CODE_PATH\": \"~/.local/bin/claude\" }","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nimport { expandTilde } from './tilde.js';\nconst configured = settings.CLAUDE_CODE_PATH;\nif (configured && !existsSync(expandTilde(configured, os.homedir()))) {\n  throw new Error(`CLAUDE_CODE_PATH is stale: ${configured} — run \\`which claude\\` and update settings.json`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["configuration","executable-resolution","filesystem","setup"],"backgroundTag":"configured-executable-not-found","analyzedSha":"e2d1df569a8f04075d40e92461128ece7cf04c82","analyzedAt":"2026-08-20T23:58:13.836Z","contentChangedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}