Hmbown/CodeWhale · error · ExecError
screen recorder produced no video
Error message
screen recorder produced no video
What it means
recordingStop verifies that the output video file exists and is non-empty after the recorder exits cleanly; if the file is missing or zero bytes, the recording produced no usable video and the library throws instead of returning an empty result.
Solutions
- Ensure some real duration between recording start and stop (record at least a few seconds).
- Check disk space and that the output directory is writable.
- Verify the intended display/window exists at start time (switch_display/list_displays).
- Retry the recording; if persistent, run the recorder command manually to inspect its behavior with zero-length output.
Example fix
// before
await backend.recordingStart({}); await backend.recordingStop({ id });
// after
await backend.recordingStart({});
await new Promise(r => setTimeout(r, 3000));
const out = await backend.recordingStop({ id }); Defensive patterns
Strategy: retry
Validate before calling
null
Try / catch
try {
const out = await backend.recordingStop({ id });
} catch (e) {
if (e.message === 'screen recorder produced no video') {
// discard, then re-record with a guaranteed minimum duration
} else throw e;
} Prevention
- Enforce a minimum recording duration (several seconds) between start and stop.
- Ensure the output directory is writable and has free space before starting.
- Verify the target display exists (list_displays) before recording it.
When it happens
Trigger: Stopping a recording where the recorder exited with code 0 but wrote nothing — e.g. recording started and stopped almost instantly, a race where the capture never began, or the output path was unwritable/cleaned up before stat.
Common situations: Start/stop called back-to-back in a script with no capture duration; a display with no content selected; disk-full or sandboxed temp directory silently swallowing output; a recorder upgrade changing output semantics.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- screen recorder failed; partial file retained
- application not found — call list_apps for exact names/pids
- background preview capture failed
- choose one available display for recording
- durationSec must be positive
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/953a146214a8d9f9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/backends/darwin.mjs:692
} catch (error) {
requestRecordingStop(recording);
const result = await waitForRecordingStop(recording, 2_000);
if (result.terminated !== false) rec.delete(id);
throw error;
} finally {
clearTimeout(timer);
signal?.removeEventListener("abort", abort);
}
}
async function recordingStop({ id }) {
const r = rec.get(id);
if (!r) throw new ExecError(`unknown or already-finished recording "${id}"`);
requestRecordingStop(r);
const result = await waitForRecordingStop(r, 20_000);
if (result.code !== 0) throw new ExecError(result.error || "screen recorder failed; partial file retained");
const size = fs.existsSync(r.file) ? fs.statSync(r.file).size : 0;
if (!size) throw new ExecError("screen recorder produced no video");
rec.delete(id);
return { id, file: r.file, mp4: null, bytes: size, mode: r.mode, startedAt: r.startedAt, stoppedAt: new Date().toISOString() };
}
async function closeSession() {
// The preview this session showed must not outlive the session; a panel
// from a dead session has no owner to refresh or hide it.
stopPreviewLoop();
await quiescePreview();
if (state.previewEnabled && state.inputApp) {
try { await native("preview_notify", { enabled: false }); } catch { /* hiding is best-effort */ }
}
state.previewEnabled = false;
await browser.close().catch(() => {});
const owned = [...rec.entries()];
for (const [, recording] of owned) requestRecordingStop(recording);
const results = await Promise.all(owned.map(async ([id, recording]) => {
const result = await waitForRecordingStop(recording, 2_000);View on GitHub (pinned to 73e0f67d83)