Skip to content

fix(library-identity-consumer): log error.cause on writer failure so PG diagnostics surface#975

Open
jakebromberg wants to merge 2 commits into
mainfrom
library-identity-consumer-error-logging
Open

fix(library-identity-consumer): log error.cause on writer failure so PG diagnostics surface#975
jakebromberg wants to merge 2 commits into
mainfrom
library-identity-consumer-error-logging

Conversation

@jakebromberg
Copy link
Copy Markdown
Member

Summary

  • Drizzle wraps every postgres-js failure in `DrizzleQueryError`, whose `.message` is hardcoded to `Failed query: \nparams: ` (drizzle-orm/errors.cjs:35-44). The actual PG error (`code`, `detail`, `constraint_name`, `column_name`) lives on `.cause`.
  • The orchestrator's catch block only captured `(error as Error).message`. During the 2026-05-20 first prod run of `library-identity-consumer`, every one of the 14,405 `single_artist` resolves failed at write, producing 14,405 identical `Failed query: INSERT INTO ...library_identity_source...` log lines with no PG diagnostic. Diagnosis required a manual psql repro.
  • Patch: extend the `warn` log line to also surface `error.cause`'s standard PostgresError properties (`pg_message`, `pg_code`, `pg_detail`, `pg_constraint`, `pg_column`, `pg_table`, `pg_routine`).
  • Diff is +19/-1 in a single file. Type-check clean against the consumer's tsconfig.

Why this is independent of the underlying writer_error root cause

Whatever fixes the actual writer failure (TBD; likely a constraint or column-shape issue surfaced by the 2026-05-20 run), the lesson stays: silently swallowing `error.cause` makes any future Drizzle-wrapped DB failure undebuggable from logs alone. This change is observability hygiene, not a behavior change.

Test plan

  • `npx tsc --noEmit -p jobs/library-identity-consumer/tsconfig.json` clean.
  • No new tests — the catch block is logging-only; behavior of the surrounding orchestration is unchanged.
  • Manual verification on next `library-identity-consumer` re-run: warn lines should include `pg_code`, `pg_constraint` etc. when `error.cause` is a PostgresError.

Followup

This unblocks the diagnosis path on #802's first-run writer failure. Underlying root cause (and a separate fix) tracked separately once the PG error surfaces.

…PG diagnostics surface

Drizzle wraps every postgres-js failure in DrizzleQueryError, whose .message is hardcoded to "Failed query: <SQL>\nparams: <params>". The actual PG error (code, detail, constraint_name, column_name) lives on .cause. The orchestrator's catch block only captured (error as Error).message, producing 14,405 identical "Failed query" log lines during the 2026-05-20 first prod run with no PG diagnostic.

Surface .cause's standard PostgresError properties on the warn log line so failures are debuggable without a manual psql repro. Field shape mirrors postgres-js's PostgresError (pg_message, pg_code, pg_detail, pg_constraint, pg_column, pg_table, pg_routine).
…message missing

- Re-flow the cause type annotation per prettier (CI format:check was failing)
- error_message falls back to String(error) for non-Error throws
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant