Phase Sweep MainSuite 1b fails at OS Phase 3: #37276 index tests are not phase-aware and blank the indicies pointer table
@fabrizzio-dotCMS is already working on this.
Since Sep 7, 2026.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Problem Statement
The weekly Scheduled OpenSearch Phase Sweep fails in the Integration Tests - MainSuite 1b [OS Phase 3] shard. The two integration test classes added by PR #37320 (for issue #37276) are not phase-aware: they hardcode setPhase(0) and setPhase(1), which is false in a job whose environment was bootstrapped at Phase 3.
At Phase 3, pointES is gated off, so the indicies table carries no Elasticsearch pointers at all. Flipping FEATURE_FLAG_OPEN_SEARCH_PHASE mid-JVM does not retroactively provision ES indices, so the ES leg resolves null index names.
Three distinct symptoms, all deterministic across the four Failsafe retries:
| Test | Phase forced | Failure |
|---|---|---|
ContentletIndexPartialFailurePhaseTest.test_dualWritePhase_shadowFailureDoesNotReachCaller |
1 | NullPointerException: index must not be null (line 101) |
ContentletIndexProviderSkipTest.test_shadowProviderSkip_stillCompletesTheRemoval |
1 | DotRuntimeException: ... the primary provider (ContentletIndexOperationsES) resolved no active index ... The removal was NOT performed. (line 119) |
ContentletIndexPartialFailurePhaseTest.test_ordinaryWrites_areUnaffectedByTheEscalation |
ambient (3) | Passes run 1, then NullPointerException: index must not be null on runs 2–4 (line 71) |
The NPE stack is identical in every case:
java.lang.NullPointerException: index must not be null
at org.elasticsearch.client.core.CountRequest.indices(CountRequest.java:92)
at ContentFactoryIndexOperationsES.getCountRequest(ContentFactoryIndexOperationsES.java:454)
at ContentFactoryIndexOperationsES.indexCount(ContentFactoryIndexOperationsES.java:446)
at ESContentFactoryImpl.indexCount(ESContentFactoryImpl.java:1607)
The production code is doing exactly what #37276 changed it to do — raising instead of silently swallowing an unresolvable index. The test premise is wrong for a Phase 3 environment, not the code.
The second, worse half: a test can blank the cluster's index pointer record
ContentletIndexProviderSkipTest.test_primaryProviderPointersUnavailable_isNotReportedAsRemoved captures a backup with loadIndicies() and restores it in a finally:
final IndiciesInfo backup = APILocator.getIndiciesAPI().loadIndicies();
try {
new DotConnect().setSQL("delete from indicies").loadResult();
...
} finally {
APILocator.getIndiciesAPI().point(backup); // backup is all-null at Phase 3
CacheLocator.getIndiciesCache().clearCache();
}
At Phase 3 that backup is already all-null, so the restore persists nulls into the indicies table and then flushes the cache. Observed 32 ms into the first execution of the class:
07:04:46.585 Setting property: FEATURE_FLAG_OPEN_SEARCH_PHASE to 0
07:04:46.617 IndiciesAPIImpl - Indices configuration updated by user: system —
working: null, live: null, reindex_working: null, reindex_live: null, site_search: null
From that moment the pointer record is gone for the rest of the fork. That is why test_ordinaryWrites_areUnaffectedByTheEscalation passes on run 1 and fails runs 2–4: Failsafe reruns in the same JVM, after the pollution. Surefire reports it as a flake; it is not — it is state leakage from a sibling test.
Note that IndiciesAPI.point() accepted an all-null IndiciesInfo without complaint. A single call was enough to blank the index pointer record for the whole instance.
Steps to Reproduce
Failing run: https://github.com/dotCMS/core/actions/runs/34016181947 (scheduled, main @ 439be9daafd2)
Locally:
- Run the MainSuite 1b integration battery under migration Phase 3:
or scope it:just test-integration-phase-all 3./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=ContentletIndexPartialFailurePhaseTest+ContentletIndexProviderSkipTestwithDOT_FEATURE_FLAG_OPEN_SEARCH_PHASE=3. test_dualWritePhase_shadowFailureDoesNotReachCallerfails on the first run withNullPointerException: index must not be null.test_shadowProviderSkip_stillCompletesTheRemovalfails withThe removal was NOT performed.- After
ContentletIndexProviderSkipTestruns, query theindiciestable — every pointer column isnull, and any subsequent ES-pathindexCountin the same JVM raises the same NPE.
Regression window: last green sweep was 2026-08-30 (run 33296639562). Commits 78689432e9 (2026-08-31) and 36b77be50b (2026-09-01), both from PR #37320, introduced these classes and registered them in MainSuite1b lines 103–104. They were written against a default (Phase 0/1) environment and had never been exercised by the Phase 3 sweep before.
Acceptance Criteria
-
ContentletIndexPartialFailurePhaseTestandContentletIndexProviderSkipTestpass — or skip cleanly — when the ambient migration phase is 3, rather than failing the shard. - Tests asserting ES-primary behaviour declare that requirement explicitly (a phase assumption such as
assumeFalse(esSameAsOs()), matching the existing idiom in the suite) instead of assuming ES pointers exist after flipping the Config flag. -
ContentletIndexProviderSkipTestnever persists an all-nullIndiciesInfo. The restore is skipped when the captured backup carries no pointers, and the test asserts that the restore actually took effect. - After the full MainSuite 1b run at Phase 3, the
indiciestable holds the same pointer values it held before the run — no test leaves the pointer record blanked. -
test_ordinaryWrites_areUnaffectedByTheEscalationproduces the same result on every Failsafe retry (no pass-then-fail flake signature caused by sibling state leakage). -
IndiciesAPI.point()rejects — or at minimum logs a warning for — anIndiciesInfowith no pointers set, so no caller can silently blank the record. - The
Scheduled OpenSearch Phase SweepMainSuite 1b [OS Phase 3] shard is green.
dotCMS Version
Latest from main (commit 439be9daafd2, 2026-09-06). Reproduces in CI on the scheduled Phase Sweep workflow.
Severity
Medium - Some functionality impacted
Links
- Failing run: https://github.com/dotCMS/core/actions/runs/34016181947
- Last green sweep: https://github.com/dotCMS/core/actions/runs/33296639562
- Introducing PR: https://github.com/dotCMS/core/pull/37320
- Parent issue for the code under test: #37276
- Freshdesk ticket: NA
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.