{"record":{"id":"23459375910f8488","repo":"thedotmack/claude-mem","slug":"postgres-requires-claude-mem-server-database-url-234593","errorCode":null,"errorMessage":"Postgres requires CLAUDE_MEM_SERVER_DATABASE_URL","messagePattern":"Postgres requires CLAUDE_MEM_SERVER_DATABASE_URL","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/storage/postgres/pool.ts","lineNumber":31,"sourceCode":"\nexport function createPostgresPool(config: PostgresConfig): PostgresPool {\n  return new Pool({\n    connectionString: config.connectionString,\n    max: config.max,\n    idleTimeoutMillis: config.idleTimeoutMillis,\n    connectionTimeoutMillis: config.connectionTimeoutMillis,\n    statement_timeout: config.statementTimeoutMillis,\n    ssl: config.ssl\n  });\n}\n\nexport function getSharedPostgresPool(options: { requireDatabaseUrl?: boolean } = {}): PostgresPool {\n  if (sharedPool) {\n    return sharedPool;\n  }\n  const config = parsePostgresConfig({ requireDatabaseUrl: options.requireDatabaseUrl ?? true });\n  if (!config) {\n    throw new Error('Postgres requires CLAUDE_MEM_SERVER_DATABASE_URL');\n  }\n  sharedPool = createPostgresPool(config);\n  return sharedPool;\n}\n\nexport async function withPostgresTransaction<T>(\n  pool: PostgresPool,\n  fn: (client: PostgresPoolClient) => Promise<T>\n): Promise<T> {\n  const client = await pool.connect();\n  try {\n    await client.query('BEGIN');\n    const result = await fn(client);\n    await client.query('COMMIT');\n    return result;\n  } catch (error) {\n    const err = error instanceof Error ? error : new Error(String(error));\n    logger.warn('DB', 'Postgres transaction rolled back', {}, err);","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/storage/postgres/pool.ts#L13-L49","documentation":"Thrown by getSharedPostgresPool (via parsePostgresConfig) when CLAUDE_MEM_SERVER_DATABASE_URL is unset/empty and requireDatabaseUrl is true (the default). The pool cannot be created without a connection string, so any path that needs Postgres fails immediately at startup.","triggerScenarios":"Booting the server/worker without CLAUDE_MEM_SERVER_DATABASE_URL set in the environment, or calling getSharedPostgresPool() with the default options when the env var is missing. Empty string is treated as missing.","commonSituations":"Missing .env in local dev, forgotten env var in CI or container, typo in variable name, deploying without provisioning the DB, or a wrapper script not exporting the variable.","solutions":["Set CLAUDE_MEM_SERVER_DATABASE_URL to a valid postgres:// connection string in the environment (.env, docker env, CI secrets).","If Postgres is optional for this code path, call getSharedPostgresPool({requireDatabaseUrl:false}) and handle the null config gracefully.","Verify the variable is actually exported to the process (print process.env keys, not the value)."],"exampleFix":"# before\n# .env missing the var\n# after (.env)\nCLAUDE_MEM_SERVER_DATABASE_URL=postgres://user:pass@localhost:5432/claude_mem","handlingStrategy":"validation","validationCode":"if (!process.env.CLAUDE_MEM_SERVER_DATABASE_URL) {\n  console.error('CLAUDE_MEM_SERVER_DATABASE_URL is required');\n  process.exit(1);\n}","typeGuard":"function hasDatabaseUrl(env = process.env){ return Boolean(env.CLAUDE_MEM_SERVER_DATABASE_URL); }","tryCatchPattern":"try { pool = getSharedPostgresPool(); } catch (e) { if (e.message==='Postgres requires CLAUDE_MEM_SERVER_DATABASE_URL') { /* degrade or exit */ } else throw e; }","preventionTips":["Validate required env at process start with a single startup check.","Provide a .env.example listing CLAUDE_MEM_SERVER_DATABASE_URL."],"tags":["postgres","config","env","startup","database"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}