thedotmack/claude-mem · error
Invalid Redis database in CLAUDE_MEM_REDIS_URL
Error message
Invalid Redis database in CLAUDE_MEM_REDIS_URL: ${parsed.pathname} What it means
Thrown by connectionFromUrl when the path portion of CLAUDE_MEM_REDIS_URL is supposed to select the Redis database number but does not parse to a non-negative integer. In redis://host:port/db, the db segment must be a valid integer >= 0 (e.g. /0, /1); anything else — non-numeric text, negative numbers, multi-segment paths — is rejected so a wrong database index never reaches the client.
Solutions
- Use a numeric database index in the path: redis://host:6379/0
- Remove the path entirely (redis://host:6379) to use the client default database
- Move any logical naming (e.g. key prefixes) to the appropriate prefix setting (see sanitizePrefix/CLAUDE_MEM queue prefix config), not the URL path
- Strip extra path segments so the URL has at most one /<integer> after the port
Example fix
// before (.env) CLAUDE_MEM_REDIS_URL=redis://localhost:6379/claude-mem // after CLAUDE_MEM_REDIS_URL=redis://localhost:6379/0
Defensive patterns
Strategy: validation
Validate before calling
const url = process.env.CLAUDE_MEM_REDIS_URL;
if (url) {
const path = new URL(url).pathname;
if (path.length > 1) {
const db = Number(path.slice(1));
if (!Number.isInteger(db) || db < 0) {
throw new Error(`Redis URL path must be a numeric db index (e.g. /0); got "${path}"`);
}
}
} Type guard
function hasValidRedisDbPath(url: string): boolean {
const path = new URL(url).pathname;
if (path.length <= 1) return true;
const db = Number(path.slice(1));
return Number.isInteger(db) && db >= 0;
} Try / catch
try {
const config = getRedisQueueConfig();
} catch (err) {
if (err instanceof Error && err.message.includes('Invalid Redis database in CLAUDE_MEM_REDIS_URL')) {
console.error('The URL path must be a numeric database index like /0 — use a key-prefix setting for names instead');
}
throw err;
} Prevention
- Remember redis URL paths are numeric DB indexes, not database names like Postgres
- Put logical names/prefixes in dedicated prefix config, never in the URL path
- Omit the path entirely to use the default database
- Copy exact connection strings from provider docs rather than hand-editing paths
When it happens
Trigger: CLAUDE_MEM_REDIS_URL ending in /abc, /-1, /0/extra (pathname '/0/extra' fails parseInt), /mydb, or a trailing path like /prefix. Any URL where parsed.pathname.length > 1 and the slice after '/' is not a clean non-negative integer throws.
Common situations: Appending a key prefix or instance name to the URL out of habit (common with Cloudflare/Upstash style endpoints); copying a Postgres-style URL with a database name like /postgres; leaving a trailing slash plus garbage; misreading the db number as a name ('sessions' instead of '0').
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
- CLAUDE_MEM_REDIS_URL must use redis:// or rediss://
- 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/38bfdba434c6e214.
Report an issue: GitHub.
Appendix: source
Thrown at src/server/queue/redis-config.ts:102
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,
};
}
function describeUrlHost(rawUrl: string): { host: string; port: number } {
const parsed = new URL(rawUrl);
return {
host: parsed.hostname || '127.0.0.1',View on GitHub (pinned to d8bc9755e7)