thedotmack/claude-mem · error
`server ${commandLabel}` is a server runtime command, but CL
Error message
`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. What it means
Thrown by assertServerRuntimeForCli() when a `server <command>` CLI operation is invoked but CLAUDE_MEM_RUNTIME is set to something other than 'server' or the legacy 'server-beta' (case-insensitive). It is a fast-fail guard so server-runtime commands don't run in a worker-only context and crash later with an opaque pool error. The message tells the operator to either switch the runtime or use the worker CLI.
Source
Thrown at src/server/runtime/ServerService.ts:453
// is invisible to the server runtime, which reads keys from Postgres. Use
// this entrypoint inside Docker / Compose.
// #2572 — wrong-runtime guard.
//
// The server operability commands (`api-key`, `keys`, `jobs`) only make
// sense in the server runtime, whose canonical store is Postgres. If they
// are invoked in a worker-only context — `CLAUDE_MEM_RUNTIME` set to `worker`,
// or no `CLAUDE_MEM_SERVER_DATABASE_URL` configured — we fail fast with an
// actionable message instead of crashing later with an opaque pool error.
//
// Phase 1d: dual-accept the persisted runtime literal (`'server'` is the new
// canonical form; `'server-beta'` remains valid for existing installs).
export function assertServerRuntimeForCli(
commandLabel: string,
env: NodeJS.ProcessEnv = process.env,
): void {
const runtime = (env.CLAUDE_MEM_RUNTIME ?? '').trim().toLowerCase();
if (runtime && runtime !== 'server' && runtime !== 'server-beta') {
throw new Error(
`\`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.',
);
}
if (!(env.CLAUDE_MEM_SERVER_DATABASE_URL ?? '').trim()) {
throw new Error(
`CLAUDE_MEM_SERVER_DATABASE_URL is required for \`server ${commandLabel}\`. ` +
'This command talks to the server Postgres backend; export the connection string before running it.',
);
}
}
export async function runServerApiKeyCli(argv: string[]): Promise<void> {
const sub = argv[0]?.toLowerCase();
const options = parseFlagArgs(argv.slice(1));
try {View on GitHub (pinned to d768ba3643)
Solutions
- Set CLAUDE_MEM_RUNTIME=server (and CLAUDE_MEM_SERVER_DATABASE_URL) in the environment before running server commands.
- If you actually intended worker operations, use the worker CLI (`worker-service ...`) instead of `server ...`.
- Unset CLAUDE_MEM_RUNTIME if this shell should be able to run server commands (the guard only fires when it is non-empty and wrong).
Example fix
// before: CLAUDE_MEM_RUNTIME=worker; running server api-key create // after: export CLAUDE_MEM_RUNTIME=server // export CLAUDE_MEM_SERVER_DATABASE_URL=postgres://... // claude-mem server api-key create
Defensive patterns
Strategy: validation
Validate before calling
function assertServerRuntime(commandLabel: string, env: NodeJS.ProcessEnv = process.env): void {
const runtime = (env.CLAUDE_MEM_RUNTIME ?? '').trim().toLowerCase();
if (runtime && runtime !== 'server' && runtime !== 'server-beta') {
throw new Error(`Set CLAUDE_MEM_RUNTIME=server to run \`server ${commandLabel}\`, or unset it.`);
}
} Type guard
function isServerRuntime(env: NodeJS.ProcessEnv): boolean {
const r = (env.CLAUDE_MEM_RUNTIME ?? '').trim().toLowerCase();
return r === '' || r === 'server' || r === 'server-beta';
} Try / catch
try {
assertServerRuntimeForCli('api-key');
} catch (error) {
console.error((error as Error).message);
// guide the operator: export CLAUDE_MEM_RUNTIME=server, or use worker-service
process.exit(1);
} Prevention
- Keep server-runtime shells and worker-runtime shells in separate env profiles.
- Use CLAUDE_MEM_RUNTIME=server consistently for any shell that runs `server ...` commands.
- For worker operations, prefer the worker-service CLI explicitly.
When it happens
Trigger: CLAUDE_MEM_RUNTIME=worker (or any non-server value) is set in the environment and the user runs `claude-mem server <command>` (e.g. server api-key ...). The message captures the offending runtime value.
Common situations: A worker-only container/terminal also has the server CLI on PATH. An operator copied env from a worker setup. The runtime variable was set to a deprecated literal.
Related errors
- CLAUDE_MEM_SERVER_DATABASE_URL is required for `server ${com
- Unknown Claude model: ${options.model}. Allowed: ${[...allow
- Invalid CLAUDE_MEM_QUEUE_ENGINE=${raw}; expected sqlite or b
- Invalid CLAUDE_MEM_REDIS_MODE=${value}; expected external, m
- Invalid CLAUDE_MEM_REDIS_PORT=${value}; expected a TCP port
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/d6d618291ec44350.
Report an issue: GitHub.