fix(data-warehouse): fail fast when CDC source has no replication slot - #71095
Merged
Merged
Conversation
A CDC-enabled source with an empty stored slot name streamed an empty slot name, which Postgres reports as `replication slot "" does not exist`. The invalidation check reads that as a recoverable slot drop, so the destructive slot-invalidation recovery runs and then dead-ends because there is no slot name to recreate. The failure surfaced as SLOT_MISSING, telling the user to "Use Repair CDC" — but Repair CDC also needs a slot name and fails identically. Guard the missing-slot configuration before streaming and classify it as a distinct non-retryable category with guidance that actually resolves it (disable and re-enable CDC). This skips the doomed peek and the dead-end recovery while still pausing the schedule via the broken marker. Generated-By: PostHog Code Task-Id: 9c79eaf9-ebd2-41ab-a403-a7f647e2d3b1
Contributor
|
Hey @Gilbert09! 👋 It looks like your git author email on this PR isn't your
You can fix it for this repo with: git config user.email "you@posthog.com"Or set it globally with |
There was a problem hiding this comment.
Contained, well-tested fix to CDC error classification/fail-fast behavior in the warehouse-sources product; author is on the owning team, diff matches the description, and no data model/API/CI/dependency risk is introduced.
- 👍 on the PR from hex-security-app[bot].
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 40L, 2F substantive, 112L/4F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1c-medium (112L, 4F, single-area, fix) |
| stamphog 2.0.0b3 | .stamphog/policy.yml @ 40bff74 · reviewed head 62d6e37 |
danielcarletti
approved these changes
Jul 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Error tracking surfaced a Postgres CDC source failing with a misleading, dead-end error. The exception chain was:
psycopg UndefinedObject: replication slot "" does not exist— note the empty slot nameRuntimeError: Cannot recreate CDC replication slot: no slot name configured for this sourceNonRetryableException: The replication slot no longer exists on the source database ... Use Repair CDC to recreate it and re-sync.The source had change data capture enabled but no replication slot name stored in its config. The extraction activity streamed with an empty slot name, which Postgres reports as
replication slot "" does not exist. The slot-invalidation check reads that as a recoverable slot drop, so it runs the destructive recovery path (resets every CDC schema to snapshot, marks them failed) and then dead-ends inrecreate_slot, which raises because there is no slot name to recreate.The failure ends up classified as
SLOT_MISSING, so the user is told to "Use Repair CDC". But Repair CDC also callsrecreate_slotand fails the same way — there is no slot name. The guidance is a dead end.Changes
Detect the missing-slot configuration up front and treat it as its own non-retryable category:
CDCSlotNotConfiguredErrorandCDCErrorCategory.SLOT_NOT_CONFIGUREDin the shared CDC error taxonomy, with actionable copy: disable and re-enable change data capture to set it up again._require_configured_slot). This skips the doomed empty-slot peek and the destructive slot-invalidation recovery entirely, and routes through the normal failure path so the source is still marked broken and the schedule stops firing.SLOT_NOT_CONFIGUREDis wired into the set of categories that mark the source broken, matchingSLOT_MISSING/PUBLICATION_MISSING.Behavior for a healthy source, and for a genuine slot-dropped source (which still correctly points at Repair CDC), is unchanged.
Note
This lives in the shared
cdc/layer, so it applies to both CDC engines (Postgres and Supabase). The guard is universally correct: a CDC source with no slot name can never stream.How did you test this code?
Automated tests only (I, Claude, did not run this against a live source):
test_extract_activity.py::TestErrorClassification::test_missing_slot_name_fails_before_streaming_without_recovery— an empty-slot CDC source raisesNonRetryableExceptionwith the new actionable message, never connects or streams, never callsrecreate_slot, and marks the source broken with reasonslot_not_configured. Catches a regression where the guard is removed and the empty-slot case again dead-ends at Repair CDC. Distinct from the existing missing-slot/publication test, which exercises a real slot name dropped on the source database (a different path).test_errors.py::TestClassifyCDCError::test_slot_not_configured_is_classified_without_adapterand a new row intest_retryable_flag— lock in that the new exception classifies toSLOT_NOT_CONFIGUREDand is non-retryable.Ran locally: the two CDC test files plus
TestSlotInvalidationRecoveryand the Postgres CDC error tests all pass.ruff checkandruff format --checkclean on the changed files.🤖 Agent context
Autonomy: Fully autonomous
Authored by Claude Code (Opus 4.8) triaging a Postgres data-warehouse CDC error from PostHog error tracking. Invoked the
/writing-testsskill before adding the regression tests.Decision: this is a fixable bug, not a user/upstream error to add to
NonRetryableErrors. The error was already non-retryable (it flows through the CDCclassify_cdc_errorpath, not the batchget_non_retryable_errorspath), so the remaining defect was the misleading dead-end guidance and the destructive recovery running on an unrecoverable config. Considered instead makingrecreate_slotregenerate a default slot name so Repair CDC could recover it, but rejected that as riskier: it would change recovery semantics and could orphan a real slot on a source that legitimately had a custom name that was lost.Created with PostHog Code