const DEFAULT_RECENT_LOG_LIMIT = 40; const RECENT_LOG_SUMMARY_LINES = 8; function toError(error: unknown, fallbackMessage: string): Error { if (error instanceof Error) return error; if (error === undefined) return new Error(fallbackMessage); if (typeof error === "string") return new Error(`${fallbackMessage}: ${error}`); try { return new Error(`${fallbackMessage}: ${JSON.stringify(error)}`); } catch { return new Error(`${fallbackMessage}: ${String(error)}`); } } function summarizeRecentLogs(recentLogs: string[]): string | null { if (recentLogs.length === 0) return null; return recentLogs .slice(-RECENT_LOG_SUMMARY_LINES) .map((line) => line.trim()) .filter((line) => line.length > 0) .join(" | "); } function detectEmbeddedPostgresHint(recentLogs: string[]): string | null { const haystack = recentLogs.join("\n").toLowerCase(); if (!haystack.includes("could not create shared memory segment")) { return null; } return ( "Embedded PostgreSQL bootstrap could not allocate shared memory. " + "On macOS, this usually means the host's kern.sysv.shm* limits are too low for another local PostgreSQL cluster. " + "Stop other local PostgreSQL servers or raise the shared-memory sysctls, then retry." ); } export function createEmbeddedPostgresLogBuffer(limit = DEFAULT_RECENT_LOG_LIMIT): { append(message: unknown): void; getRecentLogs(): string[]; } { const recentLogs: string[] = []; return { append(message: unknown) { const text = typeof message === "string" ? message : message instanceof Error ? message.message : String(message ?? ""); for (const rawLine of text.split(/\r?\n/)) { const line = rawLine.trim(); if (!line) continue; recentLogs.push(line); if (recentLogs.length > limit) { recentLogs.splice(0, recentLogs.length - limit); } } }, getRecentLogs() { return [...recentLogs]; }, }; } export function formatEmbeddedPostgresError( error: unknown, input: { fallbackMessage: string; recentLogs?: string[]; }, ): Error { const baseError = toError(error, input.fallbackMessage); const recentLogs = input.recentLogs ?? []; const parts = [baseError.message]; const hint = detectEmbeddedPostgresHint(recentLogs); const recentSummary = summarizeRecentLogs(recentLogs); if (hint) { parts.push(hint); } if (recentSummary) { parts.push(`Recent embedded Postgres logs: ${recentSummary}`); } return new Error(parts.join(" ")); }