thedotmack/claude-mem · critical

Postgres requires CLAUDE_MEM_SERVER_DATABASE_URL

Error message

Postgres requires CLAUDE_MEM_SERVER_DATABASE_URL

What it means

Thrown by parsePostgresConfig when called with requireDatabaseUrl:true but env.CLAUDE_MEM_SERVER_DATABASE_URL is unset/empty. Without requireDatabaseUrl the function returns null (allowing SQLite fallback); requiring it makes the absence fatal, since the caller needs a Postgres backend specifically.

Source

Thrown at src/storage/postgres/config.ts:32

  env?: NodeJS.ProcessEnv;
  requireDatabaseUrl?: boolean;
}

const DEFAULT_POOL_MAX = 10;
const DEFAULT_IDLE_TIMEOUT_MS = 30_000;
const DEFAULT_CONNECTION_TIMEOUT_MS = 5_000;
const DEFAULT_STATEMENT_TIMEOUT_MS = 30_000;

export function getPostgresDatabaseUrl(env: NodeJS.ProcessEnv = process.env): string | null {
  return env.CLAUDE_MEM_SERVER_DATABASE_URL || null;
}

export function parsePostgresConfig(options: ParsePostgresConfigOptions = {}): PostgresConfig | null {
  const env = options.env ?? process.env;
  const connectionString = getPostgresDatabaseUrl(env);
  if (!connectionString) {
    if (options.requireDatabaseUrl) {
      throw new Error('Postgres requires CLAUDE_MEM_SERVER_DATABASE_URL');
    }
    return null;
  }

  return {
    connectionString,
    max: parsePositiveInt(env.CLAUDE_MEM_POSTGRES_POOL_MAX, DEFAULT_POOL_MAX),
    idleTimeoutMillis: parsePositiveInt(env.CLAUDE_MEM_POSTGRES_IDLE_TIMEOUT_MS, DEFAULT_IDLE_TIMEOUT_MS),
    connectionTimeoutMillis: parsePositiveInt(env.CLAUDE_MEM_POSTGRES_CONNECTION_TIMEOUT_MS, DEFAULT_CONNECTION_TIMEOUT_MS),
    statementTimeoutMillis: parsePositiveInt(env.CLAUDE_MEM_POSTGRES_STATEMENT_TIMEOUT_MS, DEFAULT_STATEMENT_TIMEOUT_MS),
    ssl: parseSsl(connectionString, env)
  };
}

function parsePositiveInt(value: string | undefined, fallback: number): number {
  if (!value) {
    return fallback;
  }

View on GitHub (pinned to d768ba3643)

Solutions

  1. Set CLAUDE_MEM_SERVER_DATABASE_URL to a valid Postgres connection string (e.g., postgres://user:pass@host:5432/db).
  2. Confirm the env var is actually visible to the process (print process.env keys, never the value).
  3. If you did not intend to require Postgres, call parsePostgresConfig without requireDatabaseUrl so it returns null and falls back to SQLite.
  4. Use a secret manager / devkey to inject the value rather than hardcoding.

Example fix

// before
const cfg = parsePostgresConfig({ requireDatabaseUrl: true }); // throws if unset

// after
export CLAUDE_MEM_SERVER_DATABASE_URL='postgres://...' 
const cfg = parsePostgresConfig({ requireDatabaseUrl: true });
Defensive patterns

Strategy: validation

Validate before calling

if (options.requireDatabaseUrl && !process.env.CLAUDE_MEM_SERVER_DATABASE_URL) {
  throw new Error('CLAUDE_MEM_SERVER_DATABASE_URL must be set to use Postgres');
}
const cfg = parsePostgresConfig(options);

Try / catch

try {
  const cfg = parsePostgresConfig({ requireDatabaseUrl: true });
} catch (err) {
  if (err instanceof Error && /CLAUDE_MEM_SERVER_DATABASE_URL/.test(err.message)) {
    // fall back to SQLite or halt with a config error
    logger.error('DB', 'Postgres URL missing — falling back to SQLite');
    return null;
  }
  throw err;
}

Prevention

When it happens

Trigger: parsePostgresConfig({ requireDatabaseUrl: true }) (or a caller that sets it) invoked in an environment where CLAUDE_MEM_SERVER_DATABASE_URL is not set.

Common situations: Server configured to use the Postgres backend but the connection string env var wasn't provided; deployment forgot to inject the secret; .env not loaded in the process; misnamed variable.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12). Data as JSON: /api/errors/14aa82466c9f2e36. Report an issue: GitHub.