Skip to content

Flaky CI: mediaJobQueue 'debounce-persists live progress' fails with ENOENT on Windows #5512

Description

@atomantic

Problem

server/services/mediaJobQueue/index.test.js > debounce-persists live progress before a terminal transition intermittently fails on the Windows server unit tests CI job:

Error: ENOENT: no such file or directory, open '<temp>\mediaJobQueue-test-XXXXXX\media-jobs.json'

It passes reliably on a local Windows run and on the Linux CI job. Observed on PR #5502's CI (run 33354555793, attempt 1); the PR does not touch this file.

Cause

The local waitFor helper at server/services/mediaJobQueue/index.test.js:1590 calls predicate() directly:

while (Date.now() < deadline) {
  if (predicate()) return;
  await new Promise((r) => setTimeout(r, intervalMs));
}

The predicate at line 572 does JSON.parse(readFileSync(file, 'utf-8')). The persist write is debounced, so on the first poll the file may not exist yet. readFileSync throws ENOENT, and because waitFor does not catch, the throw escapes the retry loop and fails the test immediately instead of polling again. On a slow Windows runner the first poll lands inside that window often enough to flake.

Fix

Make waitFor treat a throwing predicate as "not yet true" and keep polling until the deadline, then surface the last error in the timeout message so a genuinely broken predicate is still diagnosable:

async function waitFor(predicate, { timeoutMs = 3000, intervalMs = 30 } = {}) {
  const deadline = Date.now() + timeoutMs;
  let lastError = null;
  while (Date.now() < deadline) {
    try {
      if (predicate()) return;
      lastError = null;
    } catch (err) {
      lastError = err;
    }
    await new Promise((r) => setTimeout(r, intervalMs));
  }
  throw new Error(`waitFor: predicate never became true within timeout${lastError ? `: ${lastError.message}` : ''}`);
}

Other predicates in this file that read the persisted file have the same exposure, so fixing the helper covers them all rather than guarding one call site.

Verification

Run cd server && npx vitest run services/mediaJobQueue/index.test.js — all 58 tests should still pass, and the timeout path should now report the underlying error rather than an unguarded ENOENT.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingeffort:lowEffort: lowin-progressClaimed and being workedmodel:lightModel size: lighttestsTest suite / test infrastructure

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions