thedotmack/claude-mem · error
CLAUDE_MEM_REDIS_URL must use redis:// or rediss://
Error message
CLAUDE_MEM_REDIS_URL must use redis:// or rediss://
What it means
Thrown by connectionFromUrl when CLAUDE_MEM_REDIS_URL parses as a URL but its protocol is neither redis: nor rediss:. The library only knows how to build an ioredis-style RedisOptions object from redis:// or rediss:// endpoints, and it rejects other schemes up front instead of producing a broken connection config.
Solutions
- Use a redis:// or rediss:// URL, e.g. redis://localhost:6379/0 or rediss://user:pass@host:6380
- For TLS endpoints use the rediss:// scheme (two s), not https://
- If you have a socket path, run Redis on TCP or check the library docs for socket support — do not put unix:// in this variable
- Re-check that the value was not overwritten by another service's URL (e.g. a generic REDIS_URL copy mistake)
Example fix
// before (.env) CLAUDE_MEM_REDIS_URL=https://my-redis.example.com:6379 // after CLAUDE_MEM_REDIS_URL=redis://my-redis.example.com:6379/0
Defensive patterns
Strategy: validation
Validate before calling
const url = process.env.CLAUDE_MEM_REDIS_URL;
if (url) {
const parsed = new URL(url);
if (parsed.protocol !== 'redis:' && parsed.protocol !== 'rediss:') {
throw new Error(`CLAUDE_MEM_REDIS_URL must start with redis:// or rediss://; got ${parsed.protocol}//`);
}
} Type guard
function isRedisUrl(v: string): boolean {
try {
const p = new URL(v);
return p.protocol === 'redis:' || p.protocol === 'rediss:';
} catch {
return false;
}
} Try / catch
try {
const config = getRedisQueueConfig();
} catch (err) {
if (err instanceof Error && err.message.includes('must use redis:// or rediss://')) {
console.error('Use a redis:// or rediss:// endpoint URL, not an http(s):// or socket URL');
}
throw err;
} Prevention
- Distinguish dashboard URLs (https://) from Redis endpoints (redis://) when copying from cloud consoles
- Use rediss:// (double s) for TLS endpoints
- Keep REDIS_URL and health-check/HTTP URLs in separate variables
- Validate URL scheme with new URL() in a startup config check
When it happens
Trigger: CLAUDE_MEM_REDIS_URL set to http://..., https://..., tcp://..., unix:///path/to/sock, or a bare 'localhost:6379' (which URL-parses with a non-redis protocol or fails earlier). Triggered whenever the queue config resolves a URL-based Redis connection.
Common situations: Copying a connection string from a web dashboard (often https://) instead of the Redis endpoint; using a Heroku/Render REDIS_URL that starts with redis:// is fine but an HTTP health-check URL is not; including the variable with a placeholder like https://example.com; pointing at a Unix socket path where the library expects TCP URLs.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- Invalid Redis database in CLAUDE_MEM_REDIS_URL
- Invalid CLAUDE_MEM_REDIS_MODE=
- Invalid CLAUDE_MEM_REDIS_PORT=
- Invalid CLAUDE_MEM_QUEUE_ENGINE=
- server job ID must not contain
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/73c57b37a77f1a5d.
Report an issue: GitHub.
Appendix: source
Thrown at src/server/queue/redis-config.ts:96
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,
maxRetriesPerRequest: null,
connectTimeout: 1000,
lazyConnect: true,
};
}
function connectionFromUrl(rawUrl: string): RedisOptions {
const parsed = new URL(rawUrl);
if (parsed.protocol !== 'redis:' && parsed.protocol !== 'rediss:') {
throw new Error('CLAUDE_MEM_REDIS_URL must use redis:// or rediss://');
}
const db = parsed.pathname.length > 1
? Number.parseInt(parsed.pathname.slice(1), 10)
: undefined;
if (db !== undefined && (!Number.isInteger(db) || db < 0)) {
throw new Error(`Invalid Redis database in CLAUDE_MEM_REDIS_URL: ${parsed.pathname}`);
}
return {
host: parsed.hostname || '127.0.0.1',
port: parsed.port ? Number.parseInt(parsed.port, 10) : 6379,
username: parsed.username ? decodeURIComponent(parsed.username) : undefined,
password: parsed.password ? decodeURIComponent(parsed.password) : undefined,
db,
tls: parsed.protocol === 'rediss:' ? {} : undefined,
maxRetriesPerRequest: null,
connectTimeout: 1000,
lazyConnect: true,
};View on GitHub (pinned to d8bc9755e7)