{"record":{"id":"eeec6d995a4317b4","repo":"stablyai/orca","slug":"timed-out-polling-label-after-polltimeoutms-m","errorCode":null,"errorMessage":"Timed out polling ${label} after ${pollTimeoutMs}ms.","messagePattern":"Timed out polling (.+?) after (.+?)ms\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/linux-wayland-terminal-exercise.mjs","lineNumber":46,"sourceCode":"    if (char === '\\\\r' || char === '\\\\n') continue\n    seq += 1\n    process.stdout.write('WAYLAND_TYPED_${runId}_' + seq + ':' + char + '\\\\n')\n  }\n})\n`\n}\n\nasync function pollWithTimeout(label, read) {\n  const readPromise = Promise.resolve().then(read)\n  readPromise.catch(() => undefined)\n  // Why: the unfixed Wayland GPU stall can freeze renderer protocol calls, so\n  // each poll needs its own deadline instead of relying only on waitFor's loop.\n  const result = await Promise.race([\n    readPromise.then((value) => ({ timedOut: false, value })),\n    delay(pollTimeoutMs).then(() => ({ timedOut: true, value: null }))\n  ])\n  if (result.timedOut) {\n    throw new Error(`Timed out polling ${label} after ${pollTimeoutMs}ms.`)\n  }\n  return result.value\n}\n\nasync function waitFor(label, read, timeout = terminalWaitTimeoutMs) {\n  const startedAt = Date.now()\n  let lastValue\n  while (Date.now() - startedAt < timeout) {\n    lastValue = await pollWithTimeout(label, read)\n    if (lastValue) {\n      return lastValue\n    }\n    await delay(50)\n  }\n  throw new Error(`Timed out waiting for ${label}; last value: ${JSON.stringify(lastValue)}`)\n}\n\nasync function getTerminalContent(page, charLimit = 12_000) {","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/linux-wayland-terminal-exercise.mjs#L28-L64","documentation":"pollWithTimeout races a single read against pollTimeoutMs (2500ms) and throws 'Timed out polling {label} after 2500ms.' when it does not settle. Each poll in the terminal exercise gets its own short deadline instead of relying solely on waitFor's loop, because an unfixed Wayland GPU stall can freeze a single renderer protocol call indefinitely.","triggerScenarios":"A page.evaluate read inside waitFor (store exposure, hydration, PTY binding, scrollback marker, typed marker) hangs past 2500ms due to a GPU wedge.","commonSituations":"Wayland GPU process wedged during terminal exercise in CI; renderer frozen mid-protocol.","solutions":["Read the label in the message to identify which read wedged, then check earlier phase logs.","Investigate the GPU stall root cause — the per-poll timeout is a detector, not the fix.","If a read is genuinely slow (not wedged), the underlying waitFor timeout (45s) is the larger budget."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  value = await pollWithTimeout(label, read)\n} catch (err) {\n  if (/Timed out polling/.test(err.message)) log.warn(`GPU wedge suspected at '${label}'`)\n  throw err\n}","preventionTips":["Use the label in the message to localize which renderer read wedged.","Address the GPU stall root cause; the per-poll deadline is a detector."],"tags":["wayland","gpu","timeout","terminal"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}