thedotmack/claude-mem · error
\`server \` is a server runtime command, but…
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
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.
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
Example fix
// before CLAUDE_MEM_RUNTIME=worker server api-key create --team t1 // after CLAUDE_MEM_RUNTIME=server CLAUDE_MEM_SERVER_DATABASE_URL=postgres://... server api-key create --team t1
Defensive patterns
Strategy: validation
Validate before calling
const runtime = (process.env.CLAUDE_MEM_RUNTIME ?? '').trim().toLowerCase();
if (runtime && runtime !== 'server' && runtime !== 'server-beta') {
console.error('switch to CLAUDE_MEM_RUNTIME=server (or use worker-service) before running this command');
process.exit(1);
} Type guard
function isServerRuntime(env: NodeJS.ProcessEnv): boolean {
const r = (env.CLAUDE_MEM_RUNTIME ?? '').trim().toLowerCase();
return r === 'server' || r === 'server-beta';
} Try / catch
try {
runServerApiKeyCli(argv);
} catch (e) {
if (String(e.message).includes('is a server runtime command')) {
console.error('Run with CLAUDE_MEM_RUNTIME=server or use the worker CLI.');
process.exit(1);
}
throw e;
} Prevention
- 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
When it happens
Trigger: Running a server CLI command (via runServerApiKeyCli or runServerJobsCli) with CLAUDE_MEM_RUNTIME set to e.g. 'worker', 'cli', or any non-server value.
Common situations: 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.
Understand the failure class
Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.
Related errors
- CLAUDE_MEM_SERVER_DATABASE_URL is required for \`server
- `server ` is a server runtime command, but…
- Anthropic API rejected request with HTTP 400: this model…
- API key prompt cancelled — leaving existing configuration…
- Bun installation completed but binary not found. Please…
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/bdab73a4945ebdac.
Report an issue: GitHub.
Appendix: source
Thrown at src/server/runtime/ServerService.ts:493
// 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 d8bc9755e7)