write_conflict_preserves_plan_stats.js assertion depends on a process-wide failpoint budget

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Major - P3
    • 9.1.0-rc0
    • Affects Version/s: None
    • Component/s: None
    • None
    • Query Execution
    • Fully Compatible
    • ALL
    • QE 2026-09-15
    • 0
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Problem

      jstests/noPassthrough/query/update/write_conflict_preserves_plan_stats.js asserts that a single operation observes at least 3 write conflicts:

      const kWriteConflictCount = 3;
      const fp = configureFailPoint(conn, "WTWriteConflictException", {}, {times: kWriteConflictCount});
      ...
      assert.gte(wc, kWriteConflictCount, "expected at least 3 writeConflicts");
      

      The WTWriteConflictException failpoint budget is process-wide. WT_OP_CHECK in src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h evaluates shouldFail() on every modifying WiredTiger cursor call:

      #define WT_OP_CHECK(x) \
          (((MONGO_unlikely(WTWriteConflictException.shouldFail()))) ? (WT_ROLLBACK) : (x))
      

      Call sites cover record store insert/update/remove, index insert/remove, and truncate, across wiredtiger_container.cpp, wiredtiger_index.cpp, wiredtiger_record_store.cpp, and wiredtiger_util.cpp. So times: 3 caps total activations across the whole server, not activations against the operation under test. Any concurrent write consumes part of the budget – oplog writes, the periodic noop writer, logical session cache refresh, oplog truncation, disagg storage background work – and the target update then sees fewer than 3 conflicts.

      BF-46150 shows this on enterprise-amazon2023-linux-x86-debug-tsan-all-feature-flags. The sorted updateOne subtest observed 2:

      2 is not greater than or eq 3 : sorted updateOne: expected at least 3 writeConflicts, got 2
        assertStatsAccumulated@jstests/noPassthrough/query/update/write_conflict_preserves_plan_stats.js:45:16
      

      Why it surfaced now

      The test landed 2026-03-18 in SERVER-115986. SERVER-127091 enabled the no_passthrough_disagg_override_replsets suite on the disagg TSAN variant on 2026-07-28. TSAN widens the window between arming the failpoint and running the update, so a background write claims an activation more often. The defect is latent on every other variant, where the test has passed on timing luck rather than by construction.

      Fix

      The behavior SERVER-115986 added is stat accumulation across write conflict retries. The existing equality assertion already verifies exactly that:

      assert.eq(wc + 1, parsed.attr.docsExamined, "docsExamined should equal writeConflicts+1");
      

      Relax the count assertion to require at least one conflict and keep the equality check. That verifies accumulation without requiring one operation to win the entire global failpoint budget.

      Rejected alternatives:

      • Disable the background writers (disableLogicalSessionCacheRefresh and the periodic noop writer). This narrows the race rather than closing it, and requires enumerating every background writer; disagg storage may add more.
      • Tag the test out of the disagg suite. Drops coverage that SERVER-127091 deliberately enabled.

            Assignee:
            Zixuan Zhuang
            Reporter:
            Zixuan Zhuang
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: