diff --git a/.github/workflows/migrations.yml b/.github/workflows/migrations.yml index daf41a0d984..4a6aab428ad 100644 --- a/.github/workflows/migrations.yml +++ b/.github/workflows/migrations.yml @@ -39,4 +39,4 @@ jobs: working-directory: ./packages/db env: DATABASE_URL: ${{ github.ref == 'refs/heads/main' && secrets.DATABASE_URL || github.ref == 'refs/heads/dev' && secrets.DEV_DATABASE_URL || secrets.STAGING_DATABASE_URL }} - run: bunx drizzle-kit migrate --config=./drizzle.config.ts \ No newline at end of file + run: bun run ./scripts/migrate.ts \ No newline at end of file diff --git a/apps/sim/lib/workflows/executor/execution-core.ts b/apps/sim/lib/workflows/executor/execution-core.ts index fe7b40b32fc..fc17013d0cf 100644 --- a/apps/sim/lib/workflows/executor/execution-core.ts +++ b/apps/sim/lib/workflows/executor/execution-core.ts @@ -5,6 +5,7 @@ import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' +import { filterUndefined } from '@sim/utils/object' import { mergeSubblockStateWithValues } from '@sim/workflow-persistence/subblocks' import type { Edge } from 'reactflow' import { z } from 'zod' @@ -39,6 +40,45 @@ const logger = createLogger('ExecutionCore') const EnvVarsSchema = z.record(z.string(), z.string()) +/** + * Surfaces the underlying driver error from a wrapped error chain. + * + * Drizzle wraps the original `postgres`/Node driver error as `error.cause`, + * which the logger's Error serializer drops (it only emits own-enumerable + * keys). Walking the `cause` chain and preferring the first error carrying a + * `code` exposes the diagnostic fields — notably the Postgres `code` — that + * distinguish a connection drop (`08006`), a rejected connection (`53300`), + * and a statement timeout (`57014`) behind an opaque "Failed query" message. + */ +function describeErrorCause(error: unknown): Record | undefined { + try { + let current: unknown = error instanceof Error ? error.cause : undefined + let driver: (Error & Record) | undefined + for (let depth = 0; depth < 10 && current instanceof Error; depth++) { + const candidate = current as Error & Record + if (!driver) driver = candidate + if (candidate.code !== undefined) { + driver = candidate + break + } + current = candidate.cause + } + if (!driver) return undefined + return filterUndefined({ + name: driver.name, + message: driver.message, + code: driver.code, + severity: driver.severity, + detail: driver.detail, + routine: driver.routine, + errno: driver.errno, + syscall: driver.syscall, + }) + } catch { + return undefined + } +} + export interface ExecuteWorkflowCoreOptions { snapshot: ExecutionSnapshot callbacks: ExecutionCallbacks @@ -681,7 +721,7 @@ export async function executeWorkflowCore( return result } catch (error: unknown) { - logger.error(`[${requestId}] Execution failed:`, error) + logger.error(`[${requestId}] Execution failed:`, error, { cause: describeErrorCause(error) }) await waitForLifecycleCallbacks() diff --git a/packages/db/scripts/migrate.ts b/packages/db/scripts/migrate.ts index 4918b572cf3..d8449a5775a 100644 --- a/packages/db/scripts/migrate.ts +++ b/packages/db/scripts/migrate.ts @@ -12,6 +12,7 @@ if (!url) { const client = postgres(url, { max: 1, connect_timeout: 10 }) try { + await client`SET statement_timeout = 0` await migrate(drizzle(client), { migrationsFolder: './migrations' }) console.log('Migrations applied successfully.') } catch (error) {