linebender/druid · error
called request_paint during painting
Error message
called request_paint during painting
What it means
`request_paint` panics if the surface's buffer is currently borrowed for painting (`pending_buffer_borrowed`). Requesting a new paint while a paint pass is already in progress would corrupt buffer state, so it is an explicit invariant violation.
Solutions
- Defer the repaint: set a needs-redraw flag and call `request_paint` after the current paint pass completes
- Move invalidation logic out of `paint`/draw callbacks into event handling
- Use the event loop's idle phase to schedule the repaint
Example fix
// before
impl Widget for W {
fn paint(&mut self, ctx, ...) {
ctx.request_paint(); // panics during painting
}
}
// after
impl Widget for W {
fn paint(&mut self, ctx, ...) {
self.needs_repaint = true; // handled later, outside paint
}
} Defensive patterns
Strategy: type-guard
Validate before calling
if surface_is_painting() { schedule_repaint_after_pass(); } else { surface.request_paint(); } Type guard
fn can_request_paint(pending_borrowed: bool) -> bool { !pending_borrowed } Prevention
- Never invalidate/redraw from inside paint or draw callbacks
- Defer repaint requests via a dirty flag processed outside the paint pass
- Audit widget code for ctx.request_paint() calls in paint impls
When it happens
Trigger: Calling `surface.request_paint()` re-entrantly from within a paint/draw callback, while `pending_buffer_borrowed` is `true`.
Common situations: Invalidating the widget/surface inside a `paint` implementation, or triggering redraws synchronously from drawing code.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- attaching an already in-use surface
- after rendering, no pixmap to present
- Application state already borrowed
- unexpected wayland event
- unrecognised key event
AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10).
Data as JSON: /api/errors/ea27bfa4b20b0229.
Report an issue: GitHub.
Appendix: source
Thrown at druid-shell/src/backend/wayland/surfaces/buffers.rs:115
/// This calls into user code. To avoid re-entrancy, ensure that we are not already in user
/// code (defer this call if necessary).
///
/// We will call into `WindowData` to paint the frame, and present it. If no buffers are
/// available we will set a flag, so that when one becomes available we immediately paint and
/// present. This includes if we need to resize.
pub fn request_paint(self: &Rc<Self>, window: &surface::Data) {
tracing::trace!(
"request_paint {:?} {:?}",
self.size.get(),
window.get_size()
);
// if our size is empty there is nothing to do.
if self.size.get().is_empty() {
return;
}
if self.pending_buffer_borrowed.get() {
panic!("called request_paint during painting");
}
// recreate if necessary
self.buffers_recreate();
// paint if we have a buffer available.
if self.pending_buffer_released() {
self.paint_unchecked(window);
}
// attempt to release any unused buffers.
self.buffers_drop_unused();
}
/// Paint the next frame, without checking if the buffer is free.
fn paint_unchecked(self: &Rc<Self>, window: &surface::Data) {
tracing::trace!("buffer.paint_unchecked");
let mut buf_data = self.pending_buffer_data().unwrap();View on GitHub (pinned to 0f8b1195e4)