Flaky Explorer API test occasionally fails on CI for unrelated PRs
Bug Description:
The API test Explorer and Editor - open and close in examples/api-tests/src/explorer-open-close.spec.js is flaky on CI. It fails intermittently with:
1) Explorer and Editor - open and close
Open/Close explorer and editor - ordering: 0, iteration #0:
AssertionError: Explorer widget should not exist:
expected ViewContainer{ _flags: 10, …(42) } to equal undefined
at closeExplorer (examples/api-tests/src/explorer-open-close.spec.js:121:16)
at async Context.<anonymous> (examples/api-tests/src/explorer-open-close.spec.js:69:13)The failing assertion is in the test's closeExplorer() helper:
async function closeExplorer() {
await navigatorContribution.closeView();
assert.isUndefined(await shell.revealWidget(EXPLORER_VIEW_CONTAINER_ID), 'Explorer widget should not exist');
}ApplicationShell.revealWidget resolves to a widget only while the id is still present in the shell's widget tracker (toTrackedStack, packages/core/src/browser/shell/application-shell.ts:1313). So the assertion failing means the Explorer ViewContainer was still tracked at the moment closeView() resolved, even though ApplicationShell.closeWidget awaits both waitForClosed(current) and this.pendingUpdates (application-shell.ts:1757).
That points at a race between the widget being closed/detached and its removal from the shell's tracker. The test observes the tracker in an intermediate state. Two things are worth deciding:
- whether
closeWidgetshould guarantee the widget is untracked once its promise resolves (product bug), or - whether the test should not use
revealWidget, a mutating reveal operation, as an existence check in the first place (test bug)
Note that revealWidget is not side-effect free: if the widget is still tracked, the call re-reveals it, so the assertion can perturb the very state that it is checking.
Steps to Reproduce:
- Run the browser example API tests:
npm run test:browser(or, as CI does,theia test . --plugins=local-dir:../../plugins --test-spec=../api-tests/**/*.spec.jsfromexamples/browser). - Repeat the run several times. The failure does not reproduce on every run.
- Observe that
Open/Close explorer and editor - ordering: 0, iteration #0intermittently fails on theExplorer widget should not existassertion, while the remaining ca. 836 tests pass.
Additional Information
Observed on CI in run 34631813803, job Build and Test (ubuntu-22.04, node-24.x), on 2026-09-11.
Evidence that this is a flake rather than a regression:
- Only one matrix cell failed. In the same run,
ubuntu-22.04 / node-26.x, both macOS jobs, both Windows jobs, Lint, Playwright and the production-build smoke test all passed. - Re-running the failed job with no code changes turned it green, and the whole run then reported
success. - The branch under test changed only
packages/ai-*node/common sources. Nothing underpackages/core/src/browser, the shell, or the navigator.
Unrelated but visible in the same log, in case it is relevant to runner health:
file-search:FileSearchServiceImpl ERROR Failed to search: file:///.../examples/browser/.test/target/source
Error: spawn /home/runner/work/theia/theia/examples/browser/lib/backend/native/rg ENOENT- Operating System: Ubuntu 22.04 (GitHub Actions runner), Node.js 24.x
- Theia Version: 1.75.0
Source: eclipse-theia/theia