{"record":{"id":"bdab73a4945ebdac","repo":"thedotmack/claude-mem","slug":"server-commandlabel-is-a-server-runtime-command-but-claude","errorCode":null,"errorMessage":"\\`server ${commandLabel}\\` is a server runtime command, but CLAUDE_MEM_RUNTIME=${runtime}. Set CLAUDE_MEM_RUNTIME=server (and CLAUDE_MEM_SERVER_DATABASE_URL) to run server operations, or use the worker CLI (\\`worker-service ...\\`) for the worker runtime.","messagePattern":"\\\\`server (.+?)\\\\` is a server runtime command, but CLAUDE_MEM_RUNTIME=(.+?)\\. Set CLAUDE_MEM_RUNTIME=server \\(and CLAUDE_MEM_SERVER_DATABASE_URL\\) to run server operations, or use the worker CLI \\(\\\\`worker-service \\.\\.\\.\\\\`\\) for the worker runtime\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/server/runtime/ServerService.ts","lineNumber":493,"sourceCode":"// is invisible to the server runtime, which reads keys from Postgres. Use\n// this entrypoint inside Docker / Compose.\n// #2572 — wrong-runtime guard.\n//\n// The server operability commands (`api-key`, `keys`, `jobs`) only make\n// sense in the server runtime, whose canonical store is Postgres. If they\n// are invoked in a worker-only context — `CLAUDE_MEM_RUNTIME` set to `worker`,\n// or no `CLAUDE_MEM_SERVER_DATABASE_URL` configured — we fail fast with an\n// actionable message instead of crashing later with an opaque pool error.\n//\n// Phase 1d: dual-accept the persisted runtime literal (`'server'` is the new\n// canonical form; `'server-beta'` remains valid for existing installs).\nexport function assertServerRuntimeForCli(\n  commandLabel: string,\n  env: NodeJS.ProcessEnv = process.env,\n): void {\n  const runtime = (env.CLAUDE_MEM_RUNTIME ?? '').trim().toLowerCase();\n  if (runtime && runtime !== 'server' && runtime !== 'server-beta') {\n    throw new Error(\n      `\\`server ${commandLabel}\\` is a server runtime command, but CLAUDE_MEM_RUNTIME=${runtime}. ` +\n        'Set CLAUDE_MEM_RUNTIME=server (and CLAUDE_MEM_SERVER_DATABASE_URL) to run server operations, ' +\n        'or use the worker CLI (`worker-service ...`) for the worker runtime.',\n    );\n  }\n  if (!(env.CLAUDE_MEM_SERVER_DATABASE_URL ?? '').trim()) {\n    throw new Error(\n      `CLAUDE_MEM_SERVER_DATABASE_URL is required for \\`server ${commandLabel}\\`. ` +\n        'This command talks to the server Postgres backend; export the connection string before running it.',\n    );\n  }\n}\n\nexport async function runServerApiKeyCli(argv: string[]): Promise<void> {\n  const sub = argv[0]?.toLowerCase();\n  const options = parseFlagArgs(argv.slice(1));\n\n  try {","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/server/runtime/ServerService.ts#L475-L511","documentation":"assertServerRuntimeForCli guards `server ...` CLI commands so they only run in the server runtime. It throws when CLAUDE_MEM_RUNTIME is set to anything other than 'server' or 'server-beta', because server runtime commands talk to the server Postgres backend and will not work under the worker or other runtimes.","triggerScenarios":"Running a server CLI command (via runServerApiKeyCli or runServerJobsCli) with CLAUDE_MEM_RUNTIME set to e.g. 'worker', 'cli', or any non-server value.","commonSituations":"Developers on a machine configured for the worker runtime trying to administer server API keys or jobs; CI environments exporting CLAUDE_MEM_RUNTIME=worker globally; stale shell exports from a different deployment role.","solutions":["Set CLAUDE_MEM_RUNTIME=server (or 'server-beta') before running the command","Also export CLAUDE_MEM_SERVER_DATABASE_URL so the subsequent DB check passes","Use the worker CLI (`worker-service ...`) instead if you actually intend to operate the worker runtime"],"exampleFix":"// before\nCLAUDE_MEM_RUNTIME=worker server api-key create --team t1\n// after\nCLAUDE_MEM_RUNTIME=server CLAUDE_MEM_SERVER_DATABASE_URL=postgres://... server api-key create --team t1","handlingStrategy":"validation","validationCode":"const runtime = (process.env.CLAUDE_MEM_RUNTIME ?? '').trim().toLowerCase();\nif (runtime && runtime !== 'server' && runtime !== 'server-beta') {\n  console.error('switch to CLAUDE_MEM_RUNTIME=server (or use worker-service) before running this command');\n  process.exit(1);\n}","typeGuard":"function isServerRuntime(env: NodeJS.ProcessEnv): boolean {\n  const r = (env.CLAUDE_MEM_RUNTIME ?? '').trim().toLowerCase();\n  return r === 'server' || r === 'server-beta';\n}","tryCatchPattern":"try {\n  runServerApiKeyCli(argv);\n} catch (e) {\n  if (String(e.message).includes('is a server runtime command')) {\n    console.error('Run with CLAUDE_MEM_RUNTIME=server or use the worker CLI.');\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Keep CLAUDE_MEM_RUNTIME exports scoped to shells/CI jobs for that role, not global","Wrap server commands in scripts that set required env themselves","Check `printenv CLAUDE_MEM_RUNTIME` when a command unexpectedly fails","Document which CLI subcommands belong to which runtime"],"tags":["cli","env","runtime"],"backgroundTag":"invalid-env-var-value","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"}