Skip to content

feat(desktop-gpui): recover recordings that crashed instead of leaving them failed - #2630

Draft
AatmanAJ wants to merge 1 commit into
CapSoftware:mainfrom
AatmanAJ:feat/recover-crashed-instant
Draft

AatmanAJ wants to merge 1 commit into
CapSoftware:mainfrom
AatmanAJ:feat/recover-crashed-instant

Conversation

@AatmanAJ

@AatmanAJ AatmanAJ commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Fixes the second half of #2606 for the GPUI app (which ships as Cap from 0.6.1).

Problem

Cap gave a crashed recording a label that looked exactly like a recording whose track failed. Recovery then refused it forever, even when every segment on disk was intact.

  • Tauri 0.6.0: at launch, load_upload_resume_candidate_at relabels every recording still InProgress as Failed { error: "Recording crashed" }. That covers both Instant recordings and multi-segment Studio recordings.
  • GPUI: when an Instant recording's pipeline ends while its meta still says InProgress, the stop path writes Failed { error: "instant recording stopped before completion" }. It does this even after output.mp4 has been finalized successfully.

GPUI's recovery scan only offers InProgress / NeedsRemux recordings. The shared finalizers also refuse a Failed meta as a RequiredTrackFailure. As a result, these recordings never show up in the "Incomplete Recording" prompt, and Studio and Instant both treat them as failed tracks. Anyone upgrading from 0.6.0 with a crashed recording has no way to get it back. The reporter recovered a 44:40 recording only by hand-editing three JSON files. Every completed segment was intact, and the only damage was one in-progress trailing segment per track, which recovery already rescues (rescue_pending_tmp_fragments).

Fix (GPUI only, no change to the shared recovery crate)

  • is_interrupted_failure recognises exactly the two interruption markers above. GPUI's marker becomes the shared INSTANT_STOPPED_BEFORE_COMPLETION const, so the writer and the reader can't drift apart.
  • reopened_interrupted returns the meta as it stood before the interruption: Instant goes back to InProgress { recording: false }, and Studio's status goes back to InProgress. It returns None for any other failure, and for a Studio recording whose recording-diagnostics.json still holds a requested-track failure. The scan uses it, so only recordings that are really interrupted appear in the existing "Incomplete Recording" prompt.
  • On Recover, the reopened meta is saved (under the existing UploadLock for Instant). Then the normal strict recovery runs unchanged: copy-to-workspace, manifest validation, decode and seek probes, publication.
  • If that recovery fails for any reason, the original Failed meta is written back, so a recording never loses its label in a half-recovered state.

Real track failures (any other error string, or diagnostics showing failed tracks) are never reopened. Recovery stays user-initiated, so nothing becomes an automatic upload candidate.

After recovery, an Instant recording is Complete. GPUI's upload queue already requires that before an upload can resume, and the library's retry and resume paths take over from there.

Testing

New end-to-end tests in library.rs. They encode real fragmented H.264 the way the recorder does, then drop the encoder without finishing it, so the directory looks like a killed process left it: files closed, an in-progress manifest and an unfinished trailing segment.

  • crashed_instant_recordings_are_offered_and_recovered: for both markers, the recording is offered, then recovered to Complete { fps: 30 }, and output.mp4 is ≥ 2 s and decodes every packet in-process.
  • crashed_studio_recordings_are_offered_and_recovered: a Tauri-style Failed: "Recording crashed" Studio recording is offered, recovered to Complete, and display.mp4 decodes cleanly.
  • track_failures_are_never_reopened: "required audio failed", and a crash whose diagnostics list a failed track, are neither offered nor recoverable, and the label is unchanged.
  • failed_recovery_keeps_the_interrupted_label: an unrecoverable crashed bundle keeps Failed: "Recording crashed" after a failed recovery attempt.

Results:

  • The 4 new tests pass.

  • Mutation checks: with interruption detection disabled, both recovery tests fail. With restore-on-failure removed, failed_recovery_keeps_the_interrupted_label fails.

  • Full GPUI suite (cargo +1.95.0 test --bin cap-gpui): 1159 passed, 0 failed. Clippy is clean.

  • Hand test: make a short Instant recording and a short Studio recording in GPUI, set each recording-meta.json to the Tauri crash label (Failed: "Recording crashed"), relaunch, Recover from the prompt, then play the result

@vercel

vercel Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

@AatmanAJ is attempting to deploy a commit to the Cap Software Inc Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant