{"record":{"id":"1485e132da8a3fbe","repo":"stablyai/orca","slug":"timed-out-during-label-after-timeoutms-ms","errorCode":null,"errorMessage":"Timed out during ${label} after ${timeoutMs}ms.","messagePattern":"Timed out during (.+?) after (.+?)ms\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/linux-wayland-validation-watchdog.mjs","lineNumber":20,"sourceCode":"\nconst formatError = (error) =>\n  error instanceof Error ? error.stack || error.message : String(error)\n\nfunction delay(ms) {\n  return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport async function runWithTimeout(label, action, timeoutMs) {\n  const actionPromise = Promise.resolve().then(action)\n  actionPromise.catch(() => undefined)\n  // Why: Playwright protocol calls can remain pending when the Wayland GPU\n  // path wedges, so direct renderer actions need an independent deadline.\n  const result = await Promise.race([\n    actionPromise.then((value) => ({ timedOut: false, value })),\n    delay(timeoutMs).then(() => ({ timedOut: true, value: null }))\n  ])\n  if (result.timedOut) {\n    throw new Error(`Timed out during ${label} after ${timeoutMs}ms.`)\n  }\n  return result.value\n}\n\nexport function createPhaseLogger({ startedAt, onPhase }) {\n  return (phase, details = '') => {\n    onPhase(phase)\n    const suffix = details ? ` ${details}` : ''\n    console.log(`[wayland-gpu] phase=${phase} elapsedMs=${Date.now() - startedAt}${suffix}`)\n  }\n}\n\nexport function startValidationWatchdog({ timeoutMs, onTimeout }) {\n  const timer = setTimeout(() => {\n    void Promise.resolve()\n      .then(onTimeout)\n      .then((exitCode) => {\n        process.exit(exitCode)","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/linux-wayland-validation-watchdog.mjs#L2-L38","documentation":"runWithTimeout races an action against timeoutMs and throws 'Timed out during {label} after {timeoutMs}ms.' when the action does not settle. It exists because Playwright protocol calls (page.evaluate, page.keyboard.type, window.api IPC) can remain pending when the Wayland GPU path wedges, so each direct renderer action gets an independent deadline rather than relying on Playwright's own timeout.","triggerScenarios":"A page.evaluate, page.keyboard.type, or window.api call hangs past its timeoutMs because the renderer/GPU process is wedged.","commonSituations":"Wayland GPU process stall in CI; renderer frozen so Playwright's CDP round-trips never complete; this is the primary detector the validation watchdog uses to flag the GPU wedge.","solutions":["Read the label in the message to find which renderer action wedged.","Investigate the GPU stall root cause — this timeout is the wedge detector, not the bug.","Tune timeoutMs only if an action legitimately needs longer (the defaults are 10s for actions, 30s for setup)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await runWithTimeout(label, action, timeoutMs)\n} catch (err) {\n  if (/Timed out during/.test(err.message)) log.error(`Renderer action '${label}' wedged — suspected Wayland GPU stall`)\n  throw err\n}","preventionTips":["Wrap every direct renderer action in runWithTimeout so a wedge cannot hang the whole validation indefinitely.","Use the label to localize the wedged step and investigate the GPU stall, not the timeout."],"tags":["wayland","gpu","timeout"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}