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

  1. Use a redis:// or rediss:// URL, e.g. redis://localhost:6379/0 or rediss://user:pass@host:6380
  2. For TLS endpoints use the rediss:// scheme (two s), not https://
  3. 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
  4. 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

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


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)