{"record":{"id":"c5c1c2c38bf8be8c","repo":"linebender/druid","slug":"after-rendering-no-pixmap-to-present","errorCode":null,"errorMessage":"after rendering, no pixmap to present","messagePattern":"after rendering, no pixmap to present","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"druid-shell/src/backend/x11/window.rs","lineNumber":827,"sourceCode":"                        .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\n        self.set_needs_present(false)?;\n\n        let mut buffers = borrow_mut!(self.buffers)?;\n        let pixmap = *buffers\n            .idle_pixmaps\n            .last()\n            .ok_or_else(|| anyhow!(\"after rendering, no pixmap to present\"))?;\n        let scale = self.scale.get();\n        if let Some(present) = borrow_mut!(self.present_data)?.as_mut() {\n            present.present(self.app.connection(), pixmap, self.id, &invalid, scale)?;\n            buffers.idle_pixmaps.pop();\n        } else {\n            for rect in invalid.rects() {\n                let rect = rect.to_px(scale).round();\n                let (x, y) = (rect.x0 as i16, rect.y0 as i16);\n                let (w, h) = (rect.width() as u16, rect.height() as u16);\n                self.app\n                    .connection()\n                    .copy_area(pixmap, self.id, self.gc, x, y, x, y, w, h)?;\n            }\n        }\n        Ok(())\n    }\n\n    fn show(&self) {","sourceCodeStart":809,"sourceCodeEnd":845,"githubUrl":"https://github.com/linebender/druid/blob/0f8b1195e4e073f9597f2865299c3d18f8e4005f/druid-shell/src/backend/x11/window.rs#L809-L845","documentation":"After rendering completes, `Window::render` pops an idle pixmap from the buffer pool to present to the X server; this error fires when the pool is empty, so there is no free pixmap to present. This indicates the double/triple-buffering invariant was violated — more frames are in flight than the pool has buffers, or presentation bookkeeping failed to return buffers to the idle list.","triggerScenarios":"`render` (from `redraw_now`/`handle_complete_notify`) calls `set_needs_present(false)`, borrows `buffers`, and finds `idle_pixmaps` empty because all pixmaps are still in flight (present pending, no PresentComplete processed) or `present_data` was None so earlier frames never consumed/popped correctly.","commonSituations":"X server not sending PresentCompleteNotify events (compositor issues, broken DRI3/Present extension), rendering faster than the display refresh/present completion, or a prior present error that left buffers un-returned.","solutions":["Verify the X server supports DRI3/Present and that present events are being delivered (test with a compositor disabled/enabled).","Check that every present path returns its pixmap to idle_pixmaps (or pops it consistently) — a missed event leaves the pool empty.","Reduce redraw pressure or investigate frame pacing; rendering more frames than buffers can deadlock the pool.","Update druid-shell; the X11 present buffer logic has had fixes around lost idle pixmaps."],"exampleFix":"// before\nlet pixmap = *buffers\n    .idle_pixmaps\n    .last()\n    .ok_or_else(|| anyhow!(\"after rendering, no pixmap to present\"))?;\n// after\nif buffers.idle_pixmaps.is_empty() {\n    log::warn!(\"no idle pixmap to present; skipping frame\");\n    return Ok(());\n}\nlet pixmap = *buffers.idle_pixmaps.last().unwrap();","handlingStrategy":"try-catch","validationCode":"// app-level: avoid issuing more redraws than frames presented\nif window.needs_present() { return; } // a frame is already in flight\nwindow.request_redraw();","typeGuard":"fn has_idle_pixmap(buffers: &SurfaceBuffers) -> bool {\n    !buffers.idle_pixmaps.is_empty()\n}","tryCatchPattern":"match window.render() {\n    Err(e) if e.to_string().contains(\"no pixmap to present\") => {\n        log::warn!(\"present pool exhausted; waiting for PresentComplete before next frame\");\n        window.request_redraw(); // retry once buffers return\n    },\n    other => other,\n}","preventionTips":["Throttle redraw requests to the display refresh rate","Verify DRI3/Present support in the target X environment","Investigate missing PresentCompleteNotify events if the error repeats","Keep druid-shell updated for buffer-pool fixes"],"tags":["x11","rendering","present","buffers","druid-shell"],"backgroundTag":"render-buffer-exhausted","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"}