Skip to content

Commit 4fc3c25

Browse files
committed
Refactor error logging and database URL validation in connection handling
- Simplified error logging for database connection issues, removing redundant messages while maintaining clarity. - Enhanced DATABASE_URL validation by parsing the URL to check for Supabase connection requirements, improving error handling and guidance for optimal configuration. - Updated retry logic warnings to provide clearer feedback during connection attempts in development environments.
1 parent 7c3d8ae commit 4fc3c25

File tree

2 files changed

+29
-50
lines changed

2 files changed

+29
-50
lines changed

src/pages/api/trpc/[trpc].ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,9 @@ export default createNextApiHandler({
1919
error.message.includes("P1017");
2020

2121
if (isConnectionError) {
22-
console.error(
23-
`❌ Database connection error on ${path ?? "<no-path>"}: ${error.message}`,
24-
);
25-
// Log DATABASE_URL info (without credentials) for debugging
26-
const dbUrl = process.env.DATABASE_URL;
27-
if (dbUrl) {
28-
try {
29-
const url = new URL(dbUrl);
30-
console.error(
31-
`Database URL: ${url.protocol}//${url.hostname}:${url.port}${url.pathname}`,
32-
);
33-
} catch {
34-
// Ignore URL parsing errors
35-
}
36-
}
22+
console.error(`Database connection error on ${path ?? "<no-path>"}: ${error.message}`);
3723
} else if (env.NODE_ENV === "development") {
38-
console.error(
39-
`❌ tRPC failed on ${path ?? "<no-path>"}: ${error.message}`,
40-
);
24+
console.error(`tRPC failed on ${path ?? "<no-path>"}: ${error.message}`);
4125
}
4226
},
4327
});

src/server/db.ts

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,7 @@ const withRetry = async <T>(
5050
const delay = INITIAL_RETRY_DELAY_MS * Math.pow(2, attempt - 1);
5151

5252
if (env.NODE_ENV === "development") {
53-
console.warn(
54-
`Database connection error (attempt ${attempt}/${MAX_RETRIES}), retrying in ${delay}ms...`,
55-
error instanceof Error ? error.message : String(error),
56-
);
53+
console.warn(`Database connection error, retrying in ${delay}ms (${attempt}/${MAX_RETRIES})`);
5754
}
5855

5956
await new Promise((resolve) => setTimeout(resolve, delay));
@@ -74,34 +71,32 @@ const withRetry = async <T>(
7471
const createPrismaClient = () => {
7572
// Validate DATABASE_URL is using pooled connection for Supabase
7673
const dbUrl = env.DATABASE_URL;
77-
if (dbUrl && dbUrl.includes("supabase.com")) {
78-
const isPooler = dbUrl.includes("pooler");
79-
const hasWrongPort = dbUrl.includes(":5432");
80-
const hasCorrectPort = dbUrl.includes(":6543");
81-
82-
// Critical error: Using pooler hostname with direct port
83-
if (isPooler && hasWrongPort) {
84-
console.error(
85-
"❌ CRITICAL: DATABASE_URL uses pooler hostname but wrong port (5432). " +
86-
"For Supabase connection pooler, you MUST use port 6543, not 5432. " +
87-
"Fix: Replace :5432 with :6543 in your DATABASE_URL. " +
88-
"Get correct URL from: Supabase Dashboard → Settings → Database → Connection Pooling → Transaction mode",
89-
);
90-
}
91-
// Error: Using direct connection instead of pooled
92-
else if (!isPooler && hasWrongPort) {
93-
console.error(
94-
"❌ DATABASE_URL is using direct connection (port 5432). " +
95-
"For Vercel serverless with Supabase, you MUST use the connection pooler URL (port 6543). " +
96-
"Get it from: Supabase Dashboard → Settings → Database → Connection Pooling → Transaction mode",
97-
);
98-
}
99-
// Warning: Pooler URL missing pgbouncer parameter
100-
else if (isPooler && hasCorrectPort && !dbUrl.includes("pgbouncer=true")) {
101-
console.warn(
102-
"⚠️ DATABASE_URL uses pooler but missing pgbouncer=true parameter. " +
103-
"Add ?pgbouncer=true to your connection string for optimal performance.",
104-
);
74+
if (dbUrl) {
75+
try {
76+
// Properly parse URL to validate hostname instead of substring matching
77+
const url = new URL(dbUrl);
78+
const hostname = url.hostname.toLowerCase();
79+
const port = url.port ? parseInt(url.port, 10) : (url.protocol === "postgresql:" ? 5432 : null);
80+
const isSupabase = hostname.endsWith(".supabase.com") || hostname === "supabase.com";
81+
const isPooler = hostname.includes("pooler");
82+
const searchParams = new URLSearchParams(url.search);
83+
const hasPgbouncer = searchParams.has("pgbouncer") && searchParams.get("pgbouncer") === "true";
84+
85+
if (isSupabase) {
86+
if (isPooler && port === 5432) {
87+
console.error("DATABASE_URL: pooler hostname requires port 6543, not 5432");
88+
} else if (!isPooler && port === 5432) {
89+
console.error("DATABASE_URL: use connection pooler (port 6543) for serverless");
90+
} else if (isPooler && port === 6543 && !hasPgbouncer) {
91+
console.warn("DATABASE_URL: add ?pgbouncer=true for optimal performance");
92+
}
93+
}
94+
} catch (error) {
95+
// If URL parsing fails, log warning but don't block initialization
96+
// Prisma will handle invalid URLs with its own error messages
97+
if (env.NODE_ENV === "development") {
98+
console.warn("Could not parse DATABASE_URL for validation:", error);
99+
}
105100
}
106101
}
107102

0 commit comments

Comments
 (0)