Skip to content

fix(desktop-gpui): finish uploading crashed Instant recordings and clean up the ones that captured nothing - #3106

Merged
richiemcilroy merged 8 commits into
mainfrom
fix/gpui-instant-crash-recovery
Oct 24, 2026
Merged

richiemcilroy merged 8 commits into
mainfrom
fix/gpui-instant-crash-recovery

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

When the app crashes or is force-quit during an Instant recording, the next launch can leave the share link broken for good:

  • The recording captured media. The relaunch shows the recovery toast. Recover rebuilds output.mp4 locally, but the upload can never finish: the crash left each track's manifest.json unfinished (is_complete: false, plus an entry for the segment being written), and the upload resume rightly accepts only finished manifests. The queue retries, then shows "Upload needs attention", and the cloud copy stays empty.
  • The recording captured nothing yet. There is nothing to recover, so no toast. The project stays "Recording in progress" locally, and its server video stays at "Uploading 0%".

Builds on #3089 (the cleanup journal for starts that never began).

flowchart TD
    C[Crash during an Instant recording] --> M{Media saved locally?}
    M -- yes --> R[Recover]
    R --> O[Rebuild output.mp4, as before]
    O --> S["Seal each track: keep the verified run of segments,<br/>set the unfinished tail aside as .unsealed, mark complete"]
    S --> Q[Upload queue resumes with the existing strict checks]
    Q --> V[Same video id verified on the server]
    M -- no --> A{"Lock free, saved before this launch<br/>and over 10 min ago, still in progress?"}
    A -- yes --> J[Journal as interrupted]
    J --> D[Sweep: usual account and local checks, then delete]
    D --> F[Mark the local recording failed]
    A -- no --> K[Leave it alone]
Loading

Recovered recordings now upload

  • seal_interrupted_track (crates/recording/src/upload_resume.rs:342) keeps the run of segments from segment_001 that every check collect_track makes still accepts (complete, sized, matching bytes, complete fragment tail). It renames the unfinished tail and any other unlisted media to <name>.unsealed without deleting them, then writes the manifest complete. Sealing a finished manifest changes nothing.
  • Recover seals the tracks after rebuilding and checking output.mp4, before marking the recording complete, so the queue never sees an unsealed recording (apps/desktop-gpui/src/recording.rs:1454). If sealing fails, recovery still succeeds locally and the upload fails as it did before.
  • The upload resume is unchanged: no check is relaxed.
  • A segment that finished in the instant before the crash, but was not yet written to the manifest, is not uploaded, though recovery can include it in output.mp4. Whenever sealing sets any media aside, or fails, the recording is marked preserve_local, so it stays on disk after its upload verifies even with delete-after-upload on, and the complete local copy is never deleted.

Recordings that crashed before capturing anything are cleaned up

  • adopt_crashed_at (apps/desktop-gpui/src/upload/instant_cleanup.rs:540) runs before each sweep. It journals a recording only when all of these hold:
    • its upload lock is free, so it is not live in any copy of the app;
    • its upload state was saved before this launch and over 10 minutes ago;
    • its metadata is still in progress and claims the same video;
    • its folder holds no media. A read error counts as media.
  • The entry carries the recording's own server and account from instant-upload.json, so the sweep's account check still applies, followed by its usual local checks and the recheck right before the delete.
  • After the delete, mark_crashed_recording_failed (instant_cleanup.rs:625) marks the local recording failed ("Cap closed before this recording captured anything.") and its upload cancelled, under the upload lock, and only if it still claims the video and still holds no media. Nothing local is deleted.
  • Linux keeps its own cleanup contract, so this is a no-op there, like the rest of the journal.

Contract between the app and the server

finished_segment_manifests_match_the_server_contract_fixtures (apps/desktop-gpui/src/upload.rs:2756) checks the finished segment manifest this app uploads against apps/web/__tests__/fixtures/desktop-segments/, and desktop-segments-manifest-contract.test.ts runs the server's finalization parser and recovery decoder on the same files. A format change on either side fails one of the two, and the web test runs in Recording Reliability.

Harness hook

CAP_GPUI_AUTO_RECOVER=1 presses Recover on the recovery toast (apps/desktop-gpui/src/main_window.rs:1682), the same way the other CAP_GPUI_AUTO_* hooks drive the app, because unprivileged synthetic clicks are dropped.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no new blocking issues were found.

Summary

This PR seals recovered Instant recordings for upload and cleans up interrupted recordings that captured no media.

  • Recovered Instant recordings can upload the segments saved before a crash.
  • Empty crashed recordings are marked failed after their server video is removed.

Reviews (4) · Last reviewed commit: "fix(desktop-gpui): keep a recovered reco..." · Reviewed by Greptile

@vercel

vercel Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cap-status Ready Ready Preview Oct 24, 2026 3:11pm UTC

@richiemcilroy

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

Comment thread apps/desktop-gpui/src/upload/instant_cleanup.rs
@richiemcilroy

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capy found 1 potential issue (1 high).

Open in Capy

Comment thread crates/recording/src/upload_resume.rs
@richiemcilroy

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capy found no issues.

View 2 other findings in Capy.

Open in Capy

@richiemcilroy
richiemcilroy changed the base branch from fix/gpui-instant-start-cleanup to main October 24, 2026 19:27
@richiemcilroy
richiemcilroy merged commit c33d7d6 into main Oct 24, 2026
52 of 53 checks passed

This branch was successfully deployed

2 active deployments
Preview – cap-web — ae45c346 Deployed Oct 24, 2026 by vercel[bot]
Preview – cap-status — ae45c346 Deployed Oct 24, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant