Skip to content

fix(studio): surface a render panic instead of caching an empty frame - #257

Closed
LeadcodeDev wants to merge 1 commit into
fix/studio-stale-writefrom
fix/studio-render-panic
Closed

LeadcodeDev wants to merge 1 commit into
fix/studio-stale-writefrom
fix/studio-render-panic

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Severity Low, category correctness. Location: crates/rustmotion-studio/src/editor/frames.rs:42

Impact

render_frame panics on failure (.expect("render frame"), .expect("rgba matches dimensions"), .expect("encode jpeg")). Because the panic happens in the scoped child thread and is consumed by join().unwrap_or_default(), the catch_unwind wrapper in view.rs::serve_or_render never fires — so fail_ledger().record_failure(key) is unreachable on that path and the whole retry-budget mechanism is dead code for the on-demand asset handler. Instead the empty Vec is treated as a successful render: frame_cache().insert(key, rendered.clone(), ...) caches zero bytes, and the responder replies 200 image/jpeg with an empty body. The canvas shows a permanently broken image for that (generation, frame, scale) and the cache guarantees it is never re-attempted. (The prefetch worker path calls render_frame directly and is correctly fenced.)

Fix

Return Result from render_frame_deep (propagate join()'s Err instead of unwrap_or_default), or at minimum refuse to cache/serve an empty byte vector and record it in the fail ledger so serve_or_render returns 500 and the webview keeps the previous frame.

Evidence the audit read

std::thread::scope(|scope| {
    std::thread::Builder::new()
        .stack_size(RENDER_STACK)
        .spawn_scoped(scope, || render_frame(scenario, tasks, frame, scale))
        .expect("spawn render thread")
        .join()
        .unwrap_or_default()
})

Stacked on fix/studio-stale-write, which carries the previous finding of this workstream. GitHub shows only this finding's diff; merge in order.

Part of the September 2026 audit remediation chantier. Refs #220 (RM-28).

@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 21, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 21, 2026
@LeadcodeDev
LeadcodeDev force-pushed the fix/studio-stale-write branch from a1e6edb to 3ba4914 Compare September 22, 2026 06:11
@LeadcodeDev
LeadcodeDev force-pushed the fix/studio-render-panic branch from 452e5aa to 70fc5c6 Compare September 22, 2026 06:11
@LeadcodeDev
LeadcodeDev force-pushed the fix/studio-stale-write branch from 3ba4914 to 64683cc Compare September 22, 2026 08:35
@LeadcodeDev
LeadcodeDev force-pushed the fix/studio-render-panic branch from 70fc5c6 to 378aaef Compare September 22, 2026 08:35
@LeadcodeDev
LeadcodeDev force-pushed the fix/studio-stale-write branch from 64683cc to 85f344b Compare September 22, 2026 08:45
render_frame panics on failure (.expect("render frame"), .expect("rgba
matches dimensions"), .expect("encode jpeg")). Because the panic happens in
the scoped child thread and is consumed by join().unwrap_or_default(), the
catch_unwind wrapper in view.rs::serve_or_render never fires — so
fail_ledger().record_failure(key) is unreachable on that path and the whole
retry-budget mechanism is dead code for the on-demand asset handler. Instead
the empty Vec is treated as a successful render: frame_cache().insert(key,
rendered.clone(), ...) caches zero bytes, and the responder replies 200
image/jpeg with an empty body. The canvas shows a permanently broken image
for that (generation, frame, scale) and the cache guarantees it is never re-
attempted. (The prefetch worker path calls render_frame directly and is
correctly fenced.)

Fix: Return Result from render_frame_deep (propagate join()'s Err instead of
unwrap_or_default), or at minimum refuse to cache/serve an empty byte vector
and record it in the fail ledger so serve_or_render returns 500 and the
webview keeps the previous frame.

Refs #220
@LeadcodeDev
LeadcodeDev force-pushed the fix/studio-render-panic branch from 378aaef to d85631b Compare September 22, 2026 08:45
@LeadcodeDev
LeadcodeDev deleted the branch fix/studio-stale-write September 22, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant