--- id: "bug-1473" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "controller" severity: "unknown" timestamp: "2026-07-25T19:12:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/controller/testsuite/test_config_repl.c (test-only; no production code involved)"] tags: ["config-upgrade-snapshot", "task-8.8", "test-only", "upgrade_materialization_verify", "activation-fence", "delaymgr", "test-construction", "not-a-production-bug"] related: [] legacy: true --- # bug-1473: test_second_config_marker_supersedes_first_still_installing_on_member (task 8.8) FAILED on first… ## Description test_second_config_marker_supersedes_first_still_installing_on_member (task 8.8) FAILED on first run: Expected 0 Was 1 -- the fence must clear once materialization for the latest marker (B) completes. ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause Test-construction gap, not a production bug. After releasing the checkpoint_in_progress CAS in the raced fixture, the test called the bare persist_checkpoint() to resolve the in-flight-checkpoint scenario, then read upgrade_materialization_fenced() directly -- but plain persist_checkpoint() never calls upgrade_materialization_verify() itself. That call only happens from two production call sites: apply_committed_entry's WAL_CONFIG_MARKER case (fires only on a NEW marker apply, not a bare checkpoint), and the delaymgr-driven retry trampoline (schedule_upgrade_materialization_retry), which explicitly no-ops when delaymgr is not running -- its own doc comment says so verbatim: "No-op when... the delaymgr is not running (the unit-test fixture path...) -- caller drives directly." The bare t42/t43 test fixture (used throughout test_config_repl.c) never inits a delaymgr, so nothing in the raced fixture would ever re-evaluate the fence after the resolving checkpoint landed -- the fence stayed fenced=1 even though materialization for marker B had genuinely completed. ## Fix Added an explicit upgrade_materialization_verify(c_raced) call immediately after the resolving persist_checkpoint() call, mirroring the exact pattern already used by the precedent 6.1-c fence tests earlier in this same file (which call upgrade_materialization_verify(c) directly after t43_commit_marker for the same delaymgr-less-fixture reason). Also asserted verify_rc == 0. Confirmed via log trace that upgrade_materialization_verify only logs on a fence 0->1 transition (ha.c:254-256, "never spams on repeated failed retries") -- explaining why no second ERROR line appeared for markerB in the raw log even before the fix, which was the first clue this was a missing-caller issue rather than a fence-logic issue. ## Verification _Not recorded (migrated from buglog.json)._ ## References _Not recorded (migrated from buglog.json)._