fix(data-warehouse): resolve duckgres backfill Delta path from url_pattern - #70180
Merged
EDsCODE merged 2 commits intoJul 11, 2026
Merged
Conversation
…ttern delta_table_uri built the Delta S3 path from schema.normalized_name, which keeps the source schema qualifier (Postgres public.foo -> public_foo). The loader writes the Delta folder under the unqualified DLT resource name (foo), so for schema-qualified sources the backfill read a prefix with no _delta_log and failed every retry with Generic delta kernel error: No files in log segment. Take the folder leaf from the catalog table url_pattern (the authoritative location the query engine reads); fall back to normalized_name only when no table row exists. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EDsCODE
marked this pull request as ready for review
July 10, 2026 22:46
Contributor
|
Reviews (1): Last reviewed commit: "fix(data-warehouse): resolve duckgres ba..." | Re-trigger Greptile |
fuziontech
approved these changes
Jul 10, 2026
Contributor
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
url_pattern is a user-writable field. The backfill derived the Delta folder leaf from it verbatim, dropping the normalize_identifier sanitization that both the old normalized_name path and the writer apply. Normalize the extracted leaf so injected separators cannot point the read outside the schema's own prefix. No-op for legitimate folders (already normalized). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
Newly-enabled incremental schemas from schema-qualified sources (Postgres
public.foo) never prime into duckgres. Their backfill fails every retry with:delta_table_uribuilds the Delta S3 path fromschema.normalized_name, which keeps the source schema qualifier:public.posthog_hogfunctionnormalizes topublic_posthog_hogfunction. But the v3 loader writes the Delta folder under the unqualified DLT resource name,posthog_hogfunction. So the backfill opens a prefix that has no_delta_log, delta-kernel reports "No files in log segment", and the schema retries forever until it hits the failure threshold and its live batches pile up in the failing-blocked bucket.It only bites schema-qualified incremental sources:
full_refreshtables never touch this path (they replace-write and prime immediately), and unqualified names (e.g. ad-report sources) already havenormalized_name == folder. That's why it stayed latent since the backfill primer landed (#63144) and surfaced in prod-eu, where the internal project mirrorspublic.posthog_*app tables — 33 schemas stuck, all identical error.Note
This is the source Delta read path only. The duckgres target table naming (e.g.
postgres_eu_public_posthog_alertconfiguration) is a separate concern and is intentionally left unchanged.Changes
delta_table_urinow takes the table's folder from the catalogurl_pattern— the authoritative location the query engine already reads — instead of recomputing it fromnormalized_name. The environment-correct base (settings.BUCKET_URL+folder_path(), both shared with the writer) is kept as-is, so only the diverging leaf segment changes. Falls back tonormalized_namewhen a schema has no catalog table yet (nothing to backfill).I kept
BUCKET_URLas the base rather than reconstructing the wholes3://URI fromurl_pattern, becauseurl_patternis an https URL and parsing its host into a bucket differs across prod (virtual-hosted S3) and local dev (MinIO endpoint). Rebasing only the leaf fixes the exact divergence without host-parsing fragility.How did you test this code?
I (Claude) ran these automated tests. No manual testing beyond the read-only prod-eu diagnostics that root-caused it (opening both the
normalized_namepath and theurl_patternpath for the stuck schemas — the former failed, the latter opened with files).Added
test_backfill_snapshot.py::TestDeltaTableUri— an in-memorySimpleTestCase(no DB; exercises the realnormalized_nameandfolder_path). What it catches that nothing did before:delta_table_urihad zero coverage, and this locks in that a schema-qualified source resolves the folder fromurl_pattern(posthog_hogfunction), notnormalized_name(public_posthog_hogfunction) — the exact prod regression. Cases: schema-qualified, unqualified (agreement guard), trailing-globurl_pattern, and the no-table fallback.Verified by mutation: reverting
delta_table_urito the oldnormalized_nameform fails the schema_qualified and glob_suffix cases and leaves the other two green, so the test is pinned to the behavior, not the implementation.test_backfill_snapshot.py: 4 passed.test_backfill.py+test_processor.py+test_backfill_snapshot.py: 48 passed (no regression from the changed URI).Automatic notifications
Docs update
Not applicable. Internal sink-path fix, no user-facing or documented behavior change.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Claude (Claude Code, Opus 4.8) root-caused this from a prod-eu dashboard showing 499 failing-blocked batches. Read-only diagnostics on the
warehouse-sources-duckgres-loadpod narrowed it: all 33 stuck schemas shared one error, region and bucket were correct (ruling out a region gap), and opening the Delta table at the catalogurl_patternsucceeded while the sink's computed path failed. That isolated the divergence todelta_table_uriusingnormalized_name.Decisions: fix the source read path only, not the duckgres target naming (separate, working, intentional). Derive the leaf from
url_patternrather than reconstructing the fulls3://URI from its https host (fragile across prod S3 vs local MinIO). Standalone PR rather than folding into #69098 ("unify duckgres data-import table naming"), which is already approved and concerns the target-write path — this is the source-read path in a different file.Skills invoked:
/writing-tests(to gate and shape the regression test).