{"record":{"id":"b762798fc097ce9d","repo":"Hmbown/CodeWhale","slug":"screen-recorder-failed-partial-file-retained","errorCode":null,"errorMessage":"screen recorder failed; partial file retained","messagePattern":"screen recorder failed; partial file retained","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/darwin.mjs","lineNumber":690,"sourceCode":"      return { id, pid: child.pid, file, display: disp, durationSec: durationSec ?? null, region: region ?? null, fps: 30, mode: \"ScreenCaptureKit\", startedAt,\n        ...(window ? { window: { id: window.window_id ?? null, name: window.name ?? null }, note: \"Recording the window's rect as it was at start; it does not track moves or resizes.\" } : {}) };\n    } catch (error) {\n      requestRecordingStop(recording);\n      const result = await waitForRecordingStop(recording, 2_000);\n      if (result.terminated !== false) rec.delete(id);\n      throw error;\n    } finally {\n      clearTimeout(timer);\n      signal?.removeEventListener(\"abort\", abort);\n    }\n  }\n\n  async function recordingStop({ id }) {\n    const r = rec.get(id);\n    if (!r) throw new ExecError(`unknown or already-finished recording \"${id}\"`);\n    requestRecordingStop(r);\n    const result = await waitForRecordingStop(r, 20_000);\n    if (result.code !== 0) throw new ExecError(result.error || \"screen recorder failed; partial file retained\");\n    const size = fs.existsSync(r.file) ? fs.statSync(r.file).size : 0;\n    if (!size) throw new ExecError(\"screen recorder produced no video\");\n    rec.delete(id);\n    return { id, file: r.file, mp4: null, bytes: size, mode: r.mode, startedAt: r.startedAt, stoppedAt: new Date().toISOString() };\n  }\n\n  async function closeSession() {\n    // The preview this session showed must not outlive the session; a panel\n    // from a dead session has no owner to refresh or hide it.\n    stopPreviewLoop();\n    await quiescePreview();\n    if (state.previewEnabled && state.inputApp) {\n      try { await native(\"preview_notify\", { enabled: false }); } catch { /* hiding is best-effort */ }\n    }\n    state.previewEnabled = false;\n    await browser.close().catch(() => {});\n    const owned = [...rec.entries()];\n    for (const [, recording] of owned) requestRecordingStop(recording);","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/darwin.mjs#L672-L708","documentation":"After the stop is requested, recordingStop waits up to 20s for the underlying macOS screen-recorder child process to exit; if the child exits with a nonzero code the recorder failed, and the library throws this error while deliberately keeping the partial file on disk. The recorder's own stderr text (result.error) is preferred in the message when available.","triggerScenarios":"Calling recording stop when the recorder process (e.g. screencapture/ffmpeg spawned at start) crashed, was killed, failed due to lost screen-recording permission, or hit a disk/encoder error, so its exit code is nonzero.","commonSituations":"Screen Recording permission revoked in System Settings mid-recording; recorder binary missing or incompatible after an OS update; encoder failure on very long recordings; machine sleep or user switching displays killing the capture session.","solutions":["Read the thrown message / result.error for the recorder's specific stderr and fix that root cause first.","Verify Screen Recording permission is still granted to the host app (System Settings > Privacy & Security > Screen Recording).","Inspect the retained partial file at the path from the start call — it may still be usable.","Re-start the recording and retry; if it recurs, run the recorder command manually to see the raw failure."],"exampleFix":"null","handlingStrategy":"fallback","validationCode":"null","typeGuard":null,"tryCatchPattern":"try {\n  const out = await backend.recordingStop({ id });\n} catch (e) {\n  console.error('recorder failed:', e.message);\n  // partial file is retained at the path from the start call — attempt to use it\n}","preventionTips":["Grant and periodically re-verify Screen Recording permission for the host app.","Check disk space before starting long recordings.","Log the retained partial file path from the start result for post-mortems.","Avoid sleeping/suspending the machine during active recordings."],"tags":["screen-recording","subprocess","macos"],"backgroundTag":"subprocess-exited-nonzero","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}