Repository navigation
[BUG] Task throttling tests can fail during asynchronous disposal teardown #1526
Description
Summary
src/core/task/__tests__/Task.throttle.test.ts intermittently completes all assertions and then fails the Vitest process with:
EnvironmentTeardownError: [vitest-worker]: Closing rpc while "onUserConsoleLog" was pending
The error has occurred in both a pull-request run and a main-branch run. Each run reported nine errors attributed to Task.throttle.test.ts, matching the nine tests in that file that create and dispose a Task.
Observed behavior
- PR feat(zoo-gateway): cache model catalog per session with ETag revalida… #1459 job 101053079438 passed 467 test files and 8,020 tests, then reported nine teardown errors and exited 1.
- Main run 33872111658 showed the same nine-error signature before the tested PR feat(zoo-gateway): cache model catalog per session with ETag revalida… #1459 merge result.
- PR feat(zoo-gateway): cache model catalog per session with ETag revalida… #1459 mutation job 101053079679 produced a related-test report with 432 passing suites and 1,507 passing tests, but Vitest exited 1 after teardown and related-test discovery treated the nonzero status as fatal.
- Focused and full local runs at PR feat(zoo-gateway): cache model catalog per session with ETag revalida… #1459 head passed, including the isolated throttling suite, the throttling and model-cache suites together, related-test discovery, and the non-core coverage lane.
Relevant code
Task.throttle.test.tscallstask.dispose()fromafterEachfor each Task-owning test.Task.dispose()returnsvoidafter starting command-output cleanup throughgetTaskDirectoryPath(...).then(OutputInterceptor.cleanup).catch(console.error).- The returned cleanup work is not exposed to callers, so a test hook cannot wait for it before Vitest tears down the worker.
Task.dispose.test.tsalready isolates these resources to avoid the same teardown error, but that does not provide a reusable completion contract.
Interpretation
The repeated CI signature is consistent with Task disposal logging or deferred cleanup crossing the Vitest worker teardown boundary. The logs do not identify which pending console callback wins the race, and local scheduling did not reproduce the failure. The main-branch occurrence and successful combined model-cache/throttling runs do not support PR #1459 model-cache state leakage as the cause.
Expected behavior
Callers that need deterministic shutdown should be able to wait until Task disposal cleanup and its error handling have settled. Tests should not leave Task-owned asynchronous work active after their cleanup hook completes.
Acceptance criteria
- Task disposal exposes a completion boundary for deferred cleanup without weakening production cleanup or suppressing errors.
Task.throttle.test.tsuses that boundary in its cleanup hook.- A deterministic regression test controls a deferred cleanup resource and proves disposal remains pending until that resource settles.
- Focused throttling/disposal tests, type checking, lint, and the repository test suite pass without teardown errors.
pnpm lifecycle:model-checkcontinues to pass. No lifecycle-model change is expected because the current model covers persisted delegation/store state, not live resource disposal.
Out of scope
- Stryker sandbox containment addressed by [Fix] Commits fail after users interrupt mutation tests #1525.
- StrykerJS static-mutant activation issue #6209.
- PR feat(zoo-gateway): cache model catalog per session with ETag revalida… #1459 model-cache behavior.
Activity
Merge branch 'fix/task-dispose-teardown-2o7nhyn77n069' into fix/zoo-g…
[Fix] Unit tests report teardown errors after Task cleanup (Zoo-Code-…
[Fix] Unit tests report teardown errors after Task cleanup (Zoo-Code-…