Skip to content

Audit the PRs in 1.1.0 for regressions since 1.0.0 #6399

Open

Description

@andygrove

What / Why

I'd like to go through every PR that went into 1.1.0 and look for regressions against 1.0.0, specifically the kind a reviewer could have caught from the diff. That covers wrong or silently different results, new failures, a query that used to fall back to Spark now running natively and getting it wrong, lost native coverage, slower default paths, and config or API behavior changes. Bugs that were already in 1.0.0 are out of scope. For each regression found, I also want to write down why review missed it, so the answer can go back into the review checklists and the review-comet-* skills.

The range is af534e0fa..branch-1.1, where af534e0fa is the merge base of branch-1.1 and the 1.0.0 tag. That is 399 PRs at 1.1.0-rc1, not counting #5192, which shipped in 1.0.0 as #5261. 292 of them touch production code. The other 107 only change docs, CI, tests or the Spark diffs.

This is too much for one sitting, so I've split it into phases that can run on separate days. Claude agents do the per-PR reading: Sonnet for the cheap passes and Opus for the deep reviews. I'll post the results of each phase as a comment here.

Where results go

Confirmed regressions are tracked in #6402, a WIP epic. Whenever a phase confirms a regression, rules one out, or a fix or backport for one lands, update the description of #6402 in place rather than commenting there. Add or move the entry and keep its progress line current. Each phase's full results still go in a comment here.

Phase 0: scope and script-only checks (done)

Phase 1: confirm the fix → origin links (Sonnet)

  • Start with the five fixes that aren't on branch-1.1. If any of them fixes a regression from this window, 1.1.0 ships it. None of them does: all five fix bugs that were already in 1.0.0.
  • For each of the 86 links, decide whether the origin PR introduced the bug that the fix addresses, and whether the bug was absent in 1.0.0. Done: 7 regressions, all fixed before rc1 (see [EPIC] Regressions in 1.1.0 since 1.0.0 #6402).

The output is the list of regressions that got past review and were caught after merge, plus any backport candidates for another RC or 1.1.1. The confirmed origins are also the known answers for checking the Phase 2 triage.

Phase 2: triage the 292 production PRs (scripts, then Sonnet)

  • Build one packet per PR: the production diff, the PR description, who reviewed it, which CI tiers ran, and any later fixes to its lines. Later fixes were left out, so that the calibration stayed blind.
  • Triage in batches of about 12, asking whether the PR changes behavior on a path that already ran in 1.0.0. That means new defaults, removed guards or fallbacks, an expression or operator that is now native by default, changed semantics, config parsing, error handling, or a perf rewrite of a default-path kernel. Anything unclear gets escalated. Done: 47 HIGH, 119 MEDIUM, 126 LOW.
  • Check the triage against the origins confirmed in Phase 1. If it misses more than one or two, rerun it with Opus. 5 of 7 were rated HIGH, and 3 of 5 among the blind checks. That is within tolerance, so there's no rerun.

Phase 3: deep review of the escalated PRs (Opus)

First, run the #6261 single-worker hang reproducer on 1.0.0 and 1.1.0-rc1, because #6261 isn't on branch-1.1. Then do one area per day, using the Phase 2 HIGH list in the comment below:

Each review uses review-comet-pr plus the matching area skill, and compares behavior at 1.0.0 and rc1. Every finding needs a reproducer and a sentence on why review missed it. The checklist includes the misses we've seen before: a stale rebase undoing a refactor on main, a new sibling class missing a guard its predecessor had, a loud failure turned into a silent wrong answer, timestamp label drift, sliced arrays across FFI, the two shuffle paths disagreeing, and tests that pass without testing anything (cache-vs-cache comparisons, assertions against the initial AQE plan).

Phase 4: verification (Sonnet, after each Phase 3 batch)

  • Build 1.0.0 and 1.1.0-rc1 once, then run each reproducer on both. Done for every area, with each workaround also checked on rc1.

A finding counts as a regression only if 1.0.0 gets it right and 1.1.0 doesn't, or if a loud failure became a silent wrong answer. Perf findings need evidence in the code, and only the high-impact ones get benchmarked.

Phase 5: report

Rough sizes in agent turns: Phase 1 about 180, Phase 2 about 650, Phase 3 about 2,000 across its batches, and Phase 4 about 200 plus build and test time.

Activity

  1. self-assigned this
    on Sep 29, 2026
  2. andygrove commented on Sep 29, 2026

    @andygrove
    MemberAuthor

    Phase 1 is done. Sonnet agents checked all 83 fix → origin links from the Phase 0 blame against the 1.0.0 tag, and I spot-checked the verdicts that mattered. That is 86 links minus 3 that were a main commit and its branch-1.1 backport.

    Seven are regressions, and all seven were fixed before 1.1.0-rc1. They're listed in #6402 with the introducing PR, the fix, and why review missed each one. None of the seven introducing PRs was backported to branch-1.0, and all seven fixes are in rc1. The five fixes that merged to main after the cut without reaching branch-1.1 (#6261, #5880, #5403, #5846 and #5169) all fix bugs that were already in 1.0.0, so none of them needs a backport as a regression fix.

    Of the other 76, 45 fixed bugs that were already in 1.0.0. There the blame link was noise, because the fix touched lines that a PR in the window had only moved or edited. 28 were bugs in functionality that is new in 1.1.0 and didn't break anything that worked in 1.0.0. Most of those are in the native Iceberg writer, the native Celeborn shuffle and the native in-memory cache, which are all off by default. The last 3 weren't fixes for a defect. I overrode two regression verdicts:

    The reasons review missed the seven fall into three groups:

    The seven introducing PRs (#5602, #5262, #5314, #5368, #6041, #4870 and #4775) are the known answers for checking the Phase 2 triage.

  3. andygrove commented on Sep 29, 2026

    @andygrove
    MemberAuthor

    Phase 2 is done. Sonnet agents triaged all 292 PRs that touch production code, in 25 batches. Each PR got HIGH, MEDIUM or LOW for how plausibly its diff regressed something that worked in 1.0.0. The result is 47 HIGH, 119 MEDIUM and 126 LOW. A HIGH is a reason to look closer, not a finding, and I expect most of them to turn out fine in Phase 3.

    The method changed in two ways from the plan above. First, the packets left out later fixes to each PR's lines, because including them would have given away the seven known answers from Phase 1. Second, one agent looked up my local notes, which describe some of those answers, so the later batches were told to judge each PR only from its own diff and the code.

    For calibration, five of the seven PRs behind the Phase 1 regressions were rated HIGH. Two of those five aren't clean hits: #5368 shared a batch with its own fix, and the agent that rated #5602 had read my notes. Of the five blind checks, #4775, #4870 and #5262 were rated HIGH, and #6041 and #5314 were rated MEDIUM. Both misses only showed up under a non-default configuration:

    • spark.sql.codegen.factoryMode=NO_CODEGEN on Spark 3.4
    • a fs.comet.libhdfs.schemes list naming s3 but not s3a

    Both were at least flagged as touching a default path. That's within the plan's tolerance of one or two misses, so I'm not rerunning the triage.

    The 47 HIGH PRs go to Phase 3, grouped by area:

    The dependency-upgrade review in Phase 3 starts from #5262, #5324, #5865 and #6094.

    The common reasons for a HIGH were:

    One open question goes first in Phase 3 because it could affect the release. #6261 fixed a hang that needs a single Tokio worker, and it isn't on branch-1.1. A standalone executor without spark.executor.cores gets exactly one worker. Phase 1 traced the memory-release bug in #6261 to before 1.0.0, but nobody has run the hang reproducer on 1.0.0. So it isn't known yet whether the hang is new in 1.1.0.

  4. andygrove commented on Sep 29, 2026

    @andygrove
    MemberAuthor

    Phase 3, expressions and casts: all 12 PRs have been reviewed against 1.0.0 and against Spark. Every reproducer was then run on 1.0.0 and 1.1.0-rc1 builds, which covers Phase 4 for this area. The #6261 check is done too: that hang was already in 1.0.0.

    Five regressions that ship in 1.1.0 are confirmed, and #6402 has the details:

    Each one has a draft fix PR open or in progress, linked from its issue.

    No regression was found in #5472, #5166, #5415, #5614, #5280 or #5682. Several of them fix wrong answers that 1.0.0 gave. #4816 changes the order of values in listagg only where Spark leaves that order unspecified, so it's not a regression.

    Why review missed these:

  5. andygrove commented on Sep 30, 2026

    @andygrove
    MemberAuthor

    Phase 3, planner, operators and shuffle: all 13 PRs have been reviewed against 1.0.0 and against Spark. Every reproducer was then run on 1.0.0 and 1.1.0-rc1 builds, which covers Phase 4 for this area.

    Three more regressions that ship in 1.1.0 are confirmed, and #6402 has the details:

    No regression was found in #5041, #5442, #5531, #5615, #5668, #5763 or #5803. #5421 and #5916 are deliberate trade-offs. #5421 moves partial AVG, stddev, first, last and a few others back to Spark when the final aggregate runs in Spark, mostly for anyone running without the Comet shuffle manager, because 1.0.0 could return NULL averages there. That's worth a line in the release notes. #5916 puts all of a map task's spill in one local directory, which #6010 tracks.

    One memory concern isn't verified. Since #5803, a native partial collect_list directly over UNION ALL or coalesce keeps every input batch it has read, including the columns it doesn't collect, and those aren't counted against the memory pool until the aggregate emits. I couldn't make that observable in a test on both builds.

    Why review missed these:

  6. andygrove commented on Oct 1, 2026

    @andygrove
    MemberAuthor

    Phase 3, scans: all 15 Parquet, Iceberg and Delta PRs have been reviewed against 1.0.0 and against Spark. The reproducers were then run on 1.0.0 and 1.1.0-rc1 builds, which covers Phase 4 for this area.

    Three more regressions that ship in 1.1.0 are confirmed, and #6402 has the details:

    All three have a workaround in the draft release notes (#6469), checked against the reproducers.

    No regression was found in #5262 (its scan side), #5377, #5503, #5602, #5654, #5715, #5853, #6116, #6154 or #6219. #6154 fixes wrong rows that 1.0.0 returned for some Iceberg transform residuals.

    Two findings aren't counted:

    Why review missed these:

  7. andygrove commented on Oct 1, 2026

    @andygrove
    MemberAuthor

    Phase 3, memory, FFI, config and shims: all 7 PRs have been reviewed against 1.0.0. None of them has a regression to count, so there was nothing to run on the 1.0.0 and rc1 builds for this area.

    Four findings aren't counted, but are worth knowing:

    No regression was found in #5368, #5493, #5539, #6166 or #6191's intended changes, which the upgrade guide documents. #5368's code only runs with spark.comet.exec.pyarrowUDF.enabled, and #5493's riskiest code was test-only and removed by #6066 before rc1.

  8. andygrove commented on Oct 1, 2026

    @andygrove
    MemberAuthor

    Phase 3, dependency upgrades: I reviewed the upstream changes between the versions in 1.0.0 and 1.1.0-rc1, starting from the code Comet calls on default paths. That covers DataFusion and datafusion-spark 54.1 to 55.1, arrow and parquet 58.4 to 59.3, opendal 0.57 to 0.58.2, and the 154 iceberg-rust commits from 3d84c81 to bb1e4a4. The reproducers were run on 1.0.0 and rc1 builds. This completes Phase 3.

    Two regressions that ship in 1.1.0 are confirmed, both from DataFusion 55, and #6402 has the details:

    Both were already filed, so I added the regression label and the evidence to each. Their workarounds are in the draft release notes (#6469).

    No regression was found in arrow, parquet, opendal or iceberg-rust. A few upstream changes improve on 1.0.0. Comparisons now treat -0.0 as equal to 0.0, as Spark does. map_from_entries raises Spark's DUPLICATED_MAP_KEY error. A Date32 to TIMESTAMP_NTZ overflow now errors as it does in Spark. The DataFusion review wasn't exhaustive: it didn't cover the sort-merge join and sort spill changes, row-based group values, or several string kernels.

    One gap is worth checking before rc2. Native Iceberg reads from S3, GCS or Azure now depend on opendal 0.58 installing its HTTP transport when the native library loads. That works in local runs, but no CI job reads from a real object store, so a quick S3 smoke test on the rc2 build would cover it.

    Why review missed these:

  9. andygrove commented on Oct 1, 2026

    @andygrove
    MemberAuthor

    Phase 5: what to do with each regression, and why review missed them.

    What to do with each regression

    rc2 comes from branch-1.1, where #6449 already fixes #6424 and #6464. For the other 11:

    Regression Effect Fix Recommendation
    #6423 regr_* wrong results #6451 (approved), backport #6489 rc2
    #6426 Iceberg temporal functions wrong results for rare pre-1970 inputs #6456 (approved), backport #6486 rc2
    #6334 native IF error #6458 (approved), backport #6491 rc2
    #5507 WindowGroupLimit wrong results for nested float keys #6468 (merged), backport #6487 rc2
    #6466 adaptive partial aggregation slower #6474 (merged), backport #6488 rc2
    #6505 _metadata block columns wrong results #6510 (approved), backport #6511 rc2
    #6425 DSv2 decimal functions wrong results #6455 (needs review), backport #6490 rc2 if it's reviewed in time, otherwise release note
    #5701 array_distinct/array_union wrong results with -0.0 #5750 (changes requested) rc2 if a narrow fallback is ready, otherwise release note
    #6506 empty-file conversion error error, rare #6515 (needs review) release note, fix in 1.1.1
    #6254 spilled aggregate replay error under memory pressure upstream apache/datafusion#25814 release note, fix in 1.1.1
    #6504 Iceberg nested-field evolution error none yet release note, fix in 1.1.1

    The fixes I'd take in rc2 are small, and each either falls back to Spark or restores 1.0.0's behavior. All of them except #6425 are approved or merged. The draft release notes in #6469 have a checked workaround for every entry, so anything that misses rc2 is covered there. #6515 changes when scan errors are raised, so I'd rather it had some time on main than went in at the last minute.

    Why review missed them

    Across all 20 regressions, the 7 fixed before rc1 and the 13 that shipped in it, the same few things come up:

    Ten of the 18 PRs that introduced these had a single approver.

    #6516 turns these lessons into checks in the review-comet-pr, review-comet-expression-pr and review-comet-memory-pr skills.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions