Skip to content

Commit 0fedceb

Browse files
log(db): Add db failure cause log message (#4749)
1 parent 4fa7e74 commit 0fedceb

1 file changed

Lines changed: 50 additions & 1 deletion

File tree

apps/sim/lib/workflows/executor/execution-core.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import { createLogger } from '@sim/logger'
77
import { getErrorMessage } from '@sim/utils/errors'
8+
import { filterUndefined } from '@sim/utils/object'
89
import { mergeSubblockStateWithValues } from '@sim/workflow-persistence/subblocks'
910
import type { Edge } from 'reactflow'
1011
import { z } from 'zod'
@@ -39,6 +40,49 @@ const logger = createLogger('ExecutionCore')
3940

4041
const EnvVarsSchema = z.record(z.string(), z.string())
4142

43+
/**
44+
* Surfaces the underlying driver error from a wrapped error chain.
45+
*
46+
* Drizzle wraps the original `postgres`/Node driver error as `error.cause`,
47+
* which the logger's Error serializer drops (it only emits own-enumerable
48+
* keys). Walking the chain from `error` itself and preferring the first error
49+
* carrying a `code` exposes the diagnostic fields — notably the Postgres
50+
* `code` — that distinguish a connection drop (`08006`), a rejected connection
51+
* (`53300`), and a statement timeout (`57014`) behind an opaque "Failed query"
52+
* message. Starting at `error` also captures a bare driver error that reaches
53+
* this path unwrapped; when no error in the chain carries a `code`, it falls
54+
* back to the first wrapped cause (the top-level error is already logged on its
55+
* own, so it is not echoed here).
56+
*/
57+
function describeErrorCause(error: unknown): Record<string, unknown> | undefined {
58+
try {
59+
let driver: (Error & Record<string, unknown>) | undefined
60+
let current: unknown = error
61+
for (let depth = 0; depth < 10 && current instanceof Error; depth++) {
62+
const candidate = current as Error & Record<string, unknown>
63+
if (candidate.code !== undefined) {
64+
driver = candidate
65+
break
66+
}
67+
if (depth === 1) driver = candidate
68+
current = candidate.cause
69+
}
70+
if (!driver) return undefined
71+
return filterUndefined({
72+
name: driver.name,
73+
message: driver.message,
74+
code: driver.code,
75+
severity: driver.severity,
76+
detail: driver.detail,
77+
routine: driver.routine,
78+
errno: driver.errno,
79+
syscall: driver.syscall,
80+
})
81+
} catch {
82+
return undefined
83+
}
84+
}
85+
4286
export interface ExecuteWorkflowCoreOptions {
4387
snapshot: ExecutionSnapshot
4488
callbacks: ExecutionCallbacks
@@ -682,7 +726,12 @@ export async function executeWorkflowCore(
682726

683727
return result
684728
} catch (error: unknown) {
685-
logger.error(`[${requestId}] Execution failed:`, error)
729+
const errorCause = describeErrorCause(error)
730+
logger.error(
731+
`[${requestId}] Execution failed:`,
732+
error,
733+
...(errorCause ? [{ cause: errorCause }] : [])
734+
)
686735

687736
await waitForLifecycleCallbacks()
688737

0 commit comments

Comments
 (0)