#18016·theia

Flaky Explorer API test occasionally fails on CI for unrelated PRs

Author: cdamusCreated Sep 12, 2026Updated Sep 13, 2026
Labelscitest

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:

javascript
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 closeWidget should 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:

  1. 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.js from examples/browser).
  2. Repeat the run several times. The failure does not reproduce on every run.
  3. Observe that Open/Close explorer and editor - ordering: 0, iteration #0 intermittently fails on the Explorer widget should not exist assertion, 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 under packages/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