{"record":{"id":"dd76ad9aebcc0c77","repo":"linebender/druid","slug":"window-render-piet-finish-failed","errorCode":null,"errorMessage":"Window::render - piet finish failed: {}","messagePattern":"Window::render - piet finish failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"druid-shell/src/backend/x11/window.rs","lineNumber":802,"sourceCode":"                let rect = rect.to_px(scale).round();\n                cairo_ctx.rectangle(rect.x0, rect.y0, rect.width(), rect.height());\n            }\n            cairo_ctx.clip();\n            cairo_ctx.scale(scale.x(), scale.y());\n            let mut piet_ctx = Piet::new(&cairo_ctx);\n\n            // We need to be careful with earlier returns here, because piet_ctx\n            // can panic if it isn't finish()ed. Also, we want to reset cairo's clip\n            // even on error.\n            //\n            // Note that we're borrowing the surface while calling the handler. This is ok, because\n            // we don't return control to the system or re-borrow the surface from any code that\n            // the client can call.\n            let result = self.with_handler_and_dont_check_the_other_borrows(|handler| {\n                handler.paint(&mut piet_ctx, &invalid);\n                piet_ctx\n                    .finish()\n                    .map_err(|e| anyhow!(\"Window::render - piet finish failed: {}\", e))\n            });\n            let err = match result {\n                None => {\n                    // The handler borrow failed, so finish didn't get called.\n                    piet_ctx\n                        .finish()\n                        .map_err(|e| anyhow!(\"Window::render - piet finish failed: {}\", e))\n                }\n                Some(e) => {\n                    // Finish might have errored, in which case we want to propagate it.\n                    e\n                }\n            };\n            cairo_ctx.reset_clip();\n\n            err?;\n        }\n","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/linebender/druid/blob/0f8b1195e4e073f9597f2865299c3d18f8e4005f/druid-shell/src/backend/x11/window.rs#L784-L820","documentation":"Raised in `Window::render` on X11 when `piet_ctx.finish()` fails after the client's `paint` handler ran successfully. `finish` flushes the cairo/piet drawing commands into the surface; an error here means the recorded draw operations could not be completed (e.g. an invalid render target or a draw call that poisoned the context). The message embeds the underlying piet error.","triggerScenarios":"During `render` (invoked from `redraw_now` or `handle_complete_notify`), the handler borrow succeeded so `handler.paint` ran and `piet_ctx.finish()` returned Err inside the `with_handler_and_dont_check_the_other_borrows` closure.","commonSituations":"Client `paint` code issuing draws that put the piet/cairo context into an error state (e.g. invalid image sources, zero-size targets), or the underlying X surface becoming invalid (window destroyed, resized to 0).","solutions":["Inspect the wrapped piet error text to find which draw operation failed; fix the offending draw call in the widget's paint method.","Verify the window/pixmap is valid (non-zero size, not destroyed) before painting.","Ensure piet-cairo and druid-shell versions are compatible; cairo backend bugs can surface at finish().","Wrap custom paint code defensively so it cannot leave the context in an error state (e.g. skip drawing with invalid Image/Text layouts)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// in custom widget paint code, before drawing\nif !ctx.is_target_valid() || ctx.size().is_empty() { return; }\nfor img in &images_to_draw { assert!(img.is_valid()); }","typeGuard":null,"tryCatchPattern":"match result_of_render {\n    Err(e) if e.to_string().contains(\"piet finish failed\") => {\n        log::error!(\"piet finish failed: {} — reviewing paint code for invalid draw calls\", e);\n        schedule_full_repaint();\n    },\n    other => other,\n}","preventionTips":["Never draw with stale or unloaded piet Image/Text resources","Skip painting when the widget/target size is zero","Avoid issuing draw calls that can poison the piet context","Pin compatible piet-cairo and druid-shell versions"],"tags":["x11","piet","rendering","druid-shell"],"backgroundTag":"render-finish-failed","analyzedSha":"0f8b1195e4e073f9597f2865299c3d18f8e4005f","analyzedAt":"2026-09-10T14:27:34.582Z","contentChangedAt":"2026-09-10T14:27:34.582Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}