thedotmack/claude-mem · error
Invalid CLAUDE_MEM_REDIS_MODE=
Error message
Invalid CLAUDE_MEM_REDIS_MODE=${value}; expected external, managed, or docker What it means
Thrown by normalizeRedisMode when CLAUDE_MEM_REDIS_MODE is not one of 'external', 'managed', or 'docker' (compared case-insensitively after trimming). This variable tells claude-mem how its Redis instance is provisioned so it can apply the right connection behavior. The library fails fast with the offending raw value rather than guessing a mode.
Solutions
- Set CLAUDE_MEM_REDIS_MODE to exactly one of: external, managed, docker
- Remove the variable entirely if Redis mode should be defaulted/absent
- Check for empty values produced by secret managers or docker-compose env interpolation and fix them
- Fix typos like 'extrenal' or 'docke' — spelling must match exactly after lowercasing
Example fix
// before (.env) CLAUDE_MEM_REDIS_MODE=standalone // after CLAUDE_MEM_REDIS_MODE=external
Defensive patterns
Strategy: validation
Validate before calling
const MODES = ['external','managed','docker'];
const mode = (process.env.CLAUDE_MEM_REDIS_MODE ?? '').trim().toLowerCase();
if (!MODES.includes(mode)) {
throw new Error(`CLAUDE_MEM_REDIS_MODE must be one of ${MODES.join(', ')}; got "${mode}"`);
} Type guard
function isRedisMode(v: string): v is 'external' | 'managed' | 'docker' {
return v === 'external' || v === 'managed' || v === 'docker';
} Try / catch
try {
const config = getRedisQueueConfig();
} catch (err) {
if (err instanceof Error && err.message.includes('CLAUDE_MEM_REDIS_MODE')) {
console.error('CLAUDE_MEM_REDIS_MODE must be external, managed, or docker:', err.message);
}
throw err;
} Prevention
- Use a zod enum schema for all CLAUDE_MEM_* env vars at boot
- Avoid inventing mode names; consult the docs list (external/managed/docker) before adding config
- Watch for empty-string injection from orchestrators (docker-compose, k8s ConfigMaps) and omit the key instead
- Add an env sanity check script to CI so bad values fail before deployment
When it happens
Trigger: Setting CLAUDE_MEM_REDIS_MODE to anything else: '', 'local', 'standalone', 'cluster', 'EXTERNAL ' is OK after normalization, but 'External:' with punctuation, 'self-hosted', or a boolean-like 'true' all throw. Triggered during getRedisQueueConfig() while resolving queue settings.
Common situations: Copy-pasting Redis config from another project that uses different mode names; inventing a plausible mode like 'standalone'; leaving the key present but empty in .env; a deploy tool that injects the variable as an empty string.
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
- Invalid CLAUDE_MEM_REDIS_PORT=
- CLAUDE_MEM_REDIS_URL must use redis:// or rediss://
- Invalid CLAUDE_MEM_QUEUE_ENGINE=
- Invalid Redis database in CLAUDE_MEM_REDIS_URL
- server startup configuration is invalid:
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/2e8f960491676741.
Report an issue: GitHub.
Appendix: 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 d8bc9755e7)