Skip to content

adapter: skip shardless builtins in forced migrations - #36668

Merged
def- merged 1 commit into
MaterializeInc:mainfrom
def-:pr-sql-282
May 21, 2026
Merged

def- merged 1 commit into
MaterializeInc:mainfrom
def-:pr-sql-282

Conversation

@def-

@def- def- commented May 21, 2026 •

Copy link
Copy Markdown
Contributor

Forced dev->dev evolution (#36251) iterates every Table/MV in the durable catalog, including brand-new builtins whose shards have not been registered yet. In read-only replicas this trips the "missing shard ID for builtin" bail in migrate_evolve_one, since the leader has not yet allocated the shard. Filter them out: there is nothing to evolve or replace for an object that does not yet exist in persist.

Fixes https://linear.app/materializeinc/issue/SQL-282

Follow-up to #36251

Nightly run: https://buildkite.com/materialize/nightly/builds/16506

Forced dev->dev evolution (MaterializeInc#36251) iterates every Table/MV in the
durable catalog, including brand-new builtins whose shards have not
been registered yet. In read-only replicas this trips the
"missing shard ID for builtin" bail in migrate_evolve_one, since the
leader has not yet allocated the shard. Filter them out: there is
nothing to evolve or replace for an object that does not yet exist
in persist.

Fixes https://linear.app/materializeinc/issue/SQL-282

Follow-up to MaterializeInc#36251

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@def-
def- requested a review from ggevay May 21, 2026 09:36
@def-
def- requested a review from a team as a code owner May 21, 2026 09:36
@def- def- added the release-blocker Critical issue that should block *any* release if not fixed label May 21, 2026

@ggevay ggevay left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@def-
def- enabled auto-merge (squash) May 21, 2026 12:48
@def-
def- merged commit 3a37dd1 into MaterializeInc:main May 21, 2026
178 of 180 checks passed
@def-
def- deleted the pr-sql-282 branch May 21, 2026 12:54
bobbyiliev pushed a commit to bobbyiliev/materialize that referenced this pull request May 21, 2026
…#36668)

Forced dev->dev evolution (MaterializeInc#36251) iterates every Table/MV in the
durable catalog, including brand-new builtins whose shards have not been
registered yet. In read-only replicas this trips the "missing shard ID
for builtin" bail in migrate_evolve_one, since the leader has not yet
allocated the shard. Filter them out: there is nothing to evolve or
replace for an object that does not yet exist in persist.

Fixes https://linear.app/materializeinc/issue/SQL-282

Follow-up to MaterializeInc#36251

Nightly run: https://buildkite.com/materialize/nightly/builds/16506

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
antiguru pushed a commit to antiguru/materialize that referenced this pull request May 25, 2026
…#36668)

Forced dev->dev evolution (MaterializeInc#36251) iterates every Table/MV in the
durable catalog, including brand-new builtins whose shards have not been
registered yet. In read-only replicas this trips the "missing shard ID
for builtin" bail in migrate_evolve_one, since the leader has not yet
allocated the shard. Filter them out: there is nothing to evolve or
replace for an object that does not yet exist in persist.

Fixes https://linear.app/materializeinc/issue/SQL-282

Follow-up to MaterializeInc#36251

Nightly run: https://buildkite.com/materialize/nightly/builds/16506

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
bosconi added a commit that referenced this pull request Sep 17, 2026
…rced ones (#38917)

### Motivation

Since #38864 every 0dt upgrade from a catalog written before v26.41.0 to
`main` crash-loops the new environmentd in read-only mode
([SQL-713](https://linear.app/materializeinc/issue/SQL-713)):

```
environmentd: fatal: cannot migrate builtin schemas from version 26.19.0 to version 26.43.0-dev.0:
missing shard ID for builtin SystemObjectDescription { schema_name: "mz_internal", object_type: Table, object_name: "mz_replica_hydration_history" }
```

Six jobs on
[nightly#18324](https://buildkite.com/materialize/nightly/builds/18324):
all four `Postgres CDC (before source versioning, multi-version upgrade,
...)` shards (from 0.147.0 and 26.19.0) and both `Checks Self-Managed
earliest to latest direct upgrade` shards (from 0.147.0). The same jobs
passed on
[#18320](https://buildkite.com/materialize/nightly/builds/18320), the
previous `main` nightly.

#38864 registers `MigrationStep::evolution("26.43.0-dev.0", ...,
"mz_replica_hydration_history")`. That table first shipped in v26.41.0,
so a source catalog older than that has no shard for it.
`plan_migration` keeps every step above the source version, the plan
reaches `migrate_evolve_one`, the shard lookup finds nothing, and the
read-only branch bails. In leader mode the same case returns `Ok(())`,
which is why the in-place `Checks ... upgrade` scenarios pass on the
same build and only the 0dt-preflight jobs fail.

#36668 fixed this exact bail for the *forced* dev-to-dev plan by
filtering shardless objects out of `plan_forced_migration`: "there is
nothing to evolve or replace for an object that does not yet exist in
persist." The versioned plan never got the filter, so any evolution step
for a builtin younger than the source version reproduces it. #38788's
step for `mz_cluster_replica_metrics_history` did not, only because that
table predates every supported source version.

### Description

Move the filter to the one place both plans pass through.
`Migration::run` now calls `drop_shardless` on the selected plan, forced
or versioned, before executing it; `plan_forced_migration` loses its
private copy of the same filter. A builtin with no registered shard does
not exist in persist yet, whether it was added in the target version or
the source version predates it entirely, and in both cases the leader
creates it at the target schema during bootstrap. The read-only bail in
`migrate_evolve_one` stays as the fail-fast for anything that still
reaches it.

This keeps the semantics #36668 chose rather than adding a new one: the
read-only race the bail guards against, a leader registering the shard
while a read-only process evolves it, cannot involve a builtin the
source version never had.

### Verification

New turmoil test `test_evolution_skips_builtin_without_shard`: one
builtin table with a shard and a stale fingerprint (the pre-evolution
schema), one without a shard at the current fingerprint (the shape
catalog open produces for a builtin new to the durable catalog), steps
at 0.2.0 and 0.3.0 over a 0.1.0 source, run once read-only and once as
leader. Both runs must succeed, evolve the first table, and leave the
second out of `new_fingerprints`.

- Against `main`'s `builtin_schema_migration.rs` the read-only run fails
with `missing shard ID for builtin SystemObjectDescription {
schema_name: "schema", object_type: Table, object_name: "new_table" }
(s2)`, the production message.
- With this change both runs pass, and the existing randomized
`test_builtin_schema_migration` harness passes.

Each turmoil test was run in its own process (`cargo test -p mz-adapter
--lib -- <full path> --exact`), which is what nextest does in CI.
Running the module's tests together in one process fails independently
of this change: `configure_tracing_for_turmoil` installs a global
subscriber under a `Once`, and when
`hydration_history_forced_migration_policy` (`#[mz_ore::test]`) runs
first the install fails and poisons the `Once` for every turmoil test
after it. Pre-existing, not addressed here.

`cargo fmt` clean; `cargo clippy -p mz-adapter --tests -D warnings`
clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5.1 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-blocker Critical issue that should block *any* release if not fixed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants