thedotmack/claude-mem · error
Invalid CLAUDE_MEM_REDIS_MODE=${value}; expected external, m
Error message
Invalid CLAUDE_MEM_REDIS_MODE=${value}; expected external, managed, or docker What it means
Thrown by normalizeRedisMode() when CLAUDE_MEM_REDIS_MODE (trimmed, lowercased) is not one of 'external', 'managed', or 'docker'. This classifies how Redis is provisioned for the bullmq queue. An empty/unset value also throws here, so the mode must be supplied whenever this function is reached.
Source
Thrown at src/server/queue/redis-config.ts:68
function getQueueSetting(key: keyof SettingsDefaults): string {
if (process.env[key] !== undefined) {
return process.env[key]!;
}
if (existsSync(USER_SETTINGS_PATH)) {
const value = SettingsDefaultsManager.loadFromFile(USER_SETTINGS_PATH, false)[key];
if (value !== undefined) {
return value;
}
}
return SettingsDefaultsManager.get(key);
}
function normalizeRedisMode(value: string): RedisMode {
const normalized = value.trim().toLowerCase();
if (normalized === 'external' || normalized === 'managed' || normalized === 'docker') {
return normalized;
}
throw new Error(`Invalid CLAUDE_MEM_REDIS_MODE=${value}; expected external, managed, or docker`);
}
function parseRedisPort(value: string): number {
const port = Number.parseInt(value, 10);
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
throw new Error(`Invalid CLAUDE_MEM_REDIS_PORT=${value}; expected a TCP port`);
}
return port;
}
function sanitizePrefix(value: string): string {
return (value.trim() || 'claude_mem').replace(/[^a-zA-Z0-9_-]/g, '_');
}
function connectionFromHost(host: string, port: number): RedisOptions {
return {
host,
port,View on GitHub (pinned to d768ba3643)
Solutions
- Set CLAUDE_MEM_REDIS_MODE to 'external' (your own Redis), 'managed' (a managed Redis service), or 'docker' (Redis in the Docker stack).
- Pick the value that matches your actual deployment topology.
- If you don't use bullmq, ensure CLAUDE_MEM_QUEUE_ENGINE is sqlite so this path isn't hit.
Example fix
// before: export CLAUDE_MEM_REDIS_MODE=local // after (self-hosted Redis): export CLAUDE_MEM_REDIS_MODE=external
Defensive patterns
Strategy: validation
Validate before calling
const VALID_REDIS_MODES = new Set(['external', 'managed', 'docker']);
function resolveRedisMode(): 'external' | 'managed' | 'docker' {
const v = (process.env.CLAUDE_MEM_REDIS_MODE ?? '').trim().toLowerCase();
if (!VALID_REDIS_MODES.has(v)) {
throw new Error('Set CLAUDE_MEM_REDIS_MODE to external, managed, or docker');
}
return v as 'external' | 'managed' | 'docker';
} Type guard
function isRedisMode(v: string): v is 'external' | 'managed' | 'docker' {
return v === 'external' || v === 'managed' || v === 'docker';
} Try / catch
try {
mode = normalizeRedisMode(getQueueSetting('CLAUDE_MEM_REDIS_MODE'));
} catch (error) {
console.error((error as Error).message);
process.exit(1);
} Prevention
- Document the three valid Redis modes and pick the one matching your topology.
- If you don't use bullmq, set CLAUDE_MEM_QUEUE_ENGINE=sqlite so this path isn't reached.
When it happens
Trigger: CLAUDE_MEM_REDIS_MODE is set to an invalid string (e.g. 'local', 'self-hosted', 'cloud'), or the function is called without the variable set.
Common situations: Operator invents a mode name. A stale config. The variable was expected to be optional but this code path requires it.
Related errors
- Invalid CLAUDE_MEM_REDIS_PORT=${value}; expected a TCP port
- CLAUDE_MEM_QUEUE_ENGINE is not "bullmq"
- Invalid CLAUDE_MEM_QUEUE_ENGINE=${raw}; expected sqlite or b
- CLAUDE_MEM_REDIS_URL must use redis:// or rediss://
- Invalid Redis database in CLAUDE_MEM_REDIS_URL: ${parsed.pat
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/2e8f960491676741.
Report an issue: GitHub.