Skip to content

fix(destination-postgres): re-throw COPY errors and sanitize null bytes in raw JSON - #75902

Merged
Sunil Kuruba (sunil-kuruba) merged 6 commits into
masterfrom
devin/1774972556-fix-postgres-flush-error-message
Aug 10, 2026
Merged

fix(destination-postgres): re-throw COPY errors and sanitize null bytes in raw JSON#75902
Sunil Kuruba (sunil-kuruba) merged 6 commits into
masterfrom
devin/1774972556-fix-postgres-flush-error-message

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

What

Fixes two bugs in destination-postgres:

  1. Silent error swallowing in flush(): PostgresInsertBuffer.flush() caught all exceptions during COPY but only logged them — never re-threw. This caused syncs to report success even when data failed to load into PostgreSQL.
  2. Missing null byte sanitization in raw tables mode: PostgresRawRecordFormatter serializes records to JSON for the _airbyte_data column, but did not strip \u0000 characters. PostgreSQL TEXT columns reject null bytes, causing PSQLException: unsupported Unicode escape sequence.

Resolves https://github.com/airbytehq/airbyte-internal-issues/issues/16126
Related to https://github.com/airbytehq/oncall/issues/11826

How

  • PostgresInsertBuffer.kt: Replace the log-only catch with a re-throw as SystemErrorException, including the table name and original error message. The finally block still handles cleanup.
  • PostgresRecordFormatter.kt: Add .replace("\u0000", "") on the JSON-serialized string in PostgresRawRecordFormatter. This complements the existing null byte sanitization in PostgresValueCoercer, which only handles typed StringValue fields (not JSON blobs in raw mode).
  • Patch version bump to 3.0.13.

Review guide

  1. PostgresInsertBuffer.kt — the critical change. Verify the re-throw behavior and that the finally cleanup block still executes correctly.
  2. PostgresRecordFormatter.kt — defensive null byte sanitization for raw tables mode.
  3. metadata.yaml / postgres.md — version bump and changelog.

Human review checklist:

  • e.message can be null in Kotlin. If so, the user-facing string will contain ". null" at the end. Consider whether this needs a null-safe alternative (e.g. e.message.orEmpty()).
  • Behavioral change: Syncs that were previously "succeeding" while silently dropping data on COPY failure will now correctly fail. This is intentional but may surface previously-hidden failures for users.
  • This change was not locally tested (Java/Kotlin connector without a local build environment). CI is the primary validation path.

User Impact

  • Syncs that encounter COPY errors (e.g., null bytes in data) will now correctly fail instead of silently reporting success while losing data.
  • The error message will identify the specific table that failed and include the PostgreSQL error detail.
  • In raw tables mode, null bytes in source data are now stripped from JSON before COPY, preventing the most common trigger for this error class.

Can this PR be safely reverted and rolled back?

  • YES 💚

Link to Devin session: https://app.devin.ai/sessions/32ee87594c6c4fef933ee5adc34eb1e3

…es in raw JSON

Previously, PostgresInsertBuffer.flush() caught exceptions during COPY
but only logged them, causing syncs to report false success. This fix:

1. Re-throws the exception as SystemErrorException with a descriptive
   user-facing message identifying the table and error detail.
2. Sanitizes null bytes from JSON-serialized data in raw tables mode,
   preventing PSQLException for unsupported Unicode escape sequences.

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Co-Authored-By: bot_apk <apk@cognition.ai>
@github-actions

Copy link
Copy Markdown
Contributor

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

PR Slash Commands

Airbyte Maintainers (that's you!) can execute the following slash commands on your PR:

  • 🛠️ Quick Fixes
    • /format-fix - Fixes most formatting issues.
    • /bump-version - Bumps connector versions, scraping changelog description from the PR title.
  • ❇️ AI Testing and Review (internal link: AI-SDLC Docs):
    • /ai-prove-fix - Runs prerelease readiness checks, including testing against customer connections.
    • /ai-canary-prerelease - Rolls out prerelease to 5-10 connections for canary testing.
    • /ai-review - AI-powered PR review for connector safety and quality gates.
  • 🚀 Connector Releases:
    • /publish-connectors-prerelease - Publishes pre-release connector builds (tagged as {version}-preview.{git-sha}) for all modified connectors in the PR.
    • /bump-progressive-rollout-version - Bumps connector version with an RC suffix (2.16.10-rc.1) for progressive rollouts (enableProgressiveRollout: true).
      • Example: /bump-progressive-rollout-version changelog="Add new feature for progressive rollout"
  • ☕️ JVM connectors:
    • /update-connector-cdk-version connector=<CONNECTOR_NAME> - Updates the specified connector to the latest CDK version.
      Example: /update-connector-cdk-version connector=destination-bigquery
  • 🐍 Python connectors:
    • /poe connector source-example lock - Run the Poe lock task on the source-example connector, committing the results back to the branch.
    • /poe source example lock - Alias for /poe connector source-example lock.
    • /poe source example use-cdk-branch my/branch - Pin the source-example CDK reference to the branch name specified.
    • /poe source example use-cdk-latest - Update the source-example CDK dependency to the latest available version.
  • ⚙️ Admin commands:
    • /force-merge reason="<REASON>" - Force merges the PR using admin privileges, bypassing CI checks. Requires a reason.
      Example: /force-merge reason="CI is flaky, tests pass locally"
📚 Show Repo Guidance

Helpful Resources

📝 Edit this welcome message.

@github-actions

github-actions Bot commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

destination-postgres Connector Test Results

199 tests   183 ✅  3m 6s ⏱️
 12 suites   16 💤
 12 files      0 ❌

Results for commit 0c26519.

♻️ This comment has been updated with latest results.

@sunil-kuruba
Sunil Kuruba (sunil-kuruba) marked this pull request as ready for review August 10, 2026 20:15
@sunil-kuruba
Sunil Kuruba (sunil-kuruba) requested a review from a team as a code owner August 10, 2026 20:15
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Deploy preview for airbyte-docs ready!

Project:airbyte-docs
Status: ✅  Deploy successful!
Preview URL:https://airbyte-docs-npfldp9gd-airbyte-growth.vercel.app
Latest Commit:0c26519

Deployed with vercel-action

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants