{"record":{"id":"a97fbb52785ab6fe","repo":"thedotmack/claude-mem","slug":"claude-code-path-is-set-to-describedpath-but-the-file-does","errorCode":null,"errorMessage":"CLAUDE_CODE_PATH is set to ${describedPath} 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":364,"sourceCode":"  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    const describedPath = describeConfiguredPath(settings.CLAUDE_CODE_PATH, configuredPath);\n    if (!_internals.existsSync(configuredPath)) {\n      throw new Error(\n        `CLAUDE_CODE_PATH is set to ${describedPath} 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 ${describedPath} (${probe.version}) but that CLI is too old for claude-mem — ` +\n        `it rejects flags every memory agent spawn requires (${probe.detail}). ${updateInstructions()}`","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/shared/find-claude-executable.ts#L346-L382","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before (~/.claude-mem/settings.json)\n{ \"CLAUDE_CODE_PATH\": \"~/.local/bin/claude\" }  // file deleted by reinstall\n\n// after\n{ \"CLAUDE_CODE_PATH\": \"/usr/local/bin/claude\" }  // verified with ls, or remove the key entirely","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nimport { homedir } from 'os';\nconst configured = settings.CLAUDE_CODE_PATH?.trim();\nif (configured) {\n  const p = configured.startsWith('~') ? configured.replace(/^~/, homedir()) : configured;\n  if (!existsSync(p)) console.warn(`CLAUDE_CODE_PATH points at missing file: ${p}`);\n}","typeGuard":"function isExistingFile(p: string | undefined): p is string {\n  return typeof p === 'string' && p.length > 0 && existsSync(expandTilde(p));\n}","tryCatchPattern":"try {\n  await findClaudeExecutable();\n} catch (e) {\n  if (e.message.includes('but the file does not exist')) {\n    delete settings.CLAUDE_CODE_PATH; // fall back to PATH discovery\n  } else throw e;\n}","preventionTips":["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"],"tags":["configuration","file-not-found","cli"],"backgroundTag":"file-not-found","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}