n8n-io/n8n · error · OperationalError
Database connection timed out
Error message
Database connection timed out
What it means
OperationalError thrown by DbConnectionMonitor.raceTimeout when the database ping does not complete within databaseConfig.pingTimeoutMs. The ping and the timeout race via Promise.race; the timeout firing first means the connection is unresponsive. Uses AbortController so the timer is cleared if the work wins. OperationalError signals a transient/expected condition the system should handle gracefully.
Source
Thrown at packages/@n8n/db/src/connection/db-connection-monitor.ts:280
/**
* Races `work` against `timeoutMs`, defaulting to `pingTimeoutMs`. Throws
* OperationalError on timeout so the "don't report timeouts to Sentry" rule in
* `ping()` applies. The timer is always cancelled in `finally` so it never leaks
* when `work` wins.
*/
private async raceTimeout<T>(
work: Promise<T>,
timeoutMs = this.databaseConfig.pingTimeoutMs,
): Promise<T> {
const abortController = new AbortController();
try {
return await Promise.race([
work,
setTimeoutP(timeoutMs, undefined, {
signal: abortController.signal,
}).then(() => {
throw new OperationalError('Database connection timed out');
}),
]);
} finally {
abortController.abort();
}
}
/** Destroys a pg pool client by releasing it with an error, immediately freeing its pool slot. Never throws. */
private safeDestroyClient(client: PgPoolClient): void {
try {
client.release(new Error('n8n ping timed out; destroying connection to free pool slot'));
} catch (error) {
this.logger.warn(
`Failed to destroy timed-out ping connection: ${ensureError(error).message}`,
);
}
}
View on GitHub (pinned to 5ac6606e81)
Solutions
- Increase DB pingTimeoutMs in config to a value comfortably above observed p95 ping latency.
- Check Postgres health: `SELECT * FROM pg_stat_activity;` for long-running queries holding connections, and confirm max_connections isn't exhausted.
- Verify network path: `psql -h <host> -c 'SELECT 1'` with timing; look for packet loss or high latency on the link.
- If using PgBouncer, confirm pool size and `pool_mode` are adequate and not queueing.
- Treat as transient — DbConnectionMonitor initiates recovery; ensure the n8n process has enough headroom (memory/CPU) to ride through.
Example fix
// before DB_POSTGRESDB_PING_TIMEOUT_MS=2000 // after DB_POSTGRESDB_PING_TIMEOUT_MS=10000
Defensive patterns
Strategy: retry
Validate before calling
// before relying on the connection, probe with a short timeout
const ok = await Promise.race([
pgPool.query('SELECT 1').then(() => true).catch(() => false),
setTimeoutP(pingTimeoutMs).then(() => false),
]);
if (!ok) { /* defer work, alert, or fall back */ } Type guard
function isOperationalTimeout(err: unknown): boolean {
return err instanceof OperationalError && err.message === 'Database connection timed out';
} Try / catch
try {
await runWithDb(dbWork);
} catch (err) {
if (isOperationalTimeout(err)) {
// back off and retry; the monitor is already recovering
await backoffRetry(dbWork);
} else throw err;
} Prevention
- Size pingTimeoutMs to your real network p95 plus headroom.
- Monitor pg_stat_activity for connection saturation before it becomes timeouts.
- Keep an explicit retry budget so transient DB timeouts don't fail user requests.
When it happens
Trigger: The monitor issues a periodic ping against a pg pool client; if the round-trip exceeds pingTimeoutMs (default configured in the DB config block), the timeout branch wins and rejects. Happens under network stalls, an overloaded Postgres, a saturated pool, DNS hiccups, or a firewall dropping idle connections.
Common situations: Latency between n8n and Postgres spiking (cross-AZ/region); Postgres max_connections reached so acquisition itself stalls; pg_bouncer stuck; a VPN/network partition; the pingTimeoutMs tuned too low for a high-latency link; cold starts after DB failover.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timed out after ${timeoutMs}ms waiting for database connecti
- Supabase upsert failed: ${error.message}
- Supabase query failed: ${error.message}
- Supabase delete failed: ${error.message}
- Driver not Connected
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/590de88b787a67cd.
Report an issue: GitHub.