{"record":{"id":"f99b6b25a19bae19","repo":"emilk/egui","slug":"shape-callback-passed-to-tessellator","errorCode":null,"errorMessage":"Shape::Callback passed to Tessellator","messagePattern":"Shape::Callback passed to Tessellator","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/epaint/src/tessellator.rs","lineNumber":1470,"sourceCode":"            Shape::Rect(rect_shape) => {\n                self.tessellate_rect(&rect_shape, out);\n            }\n            Shape::Text(text_shape) => {\n                if self.options.debug_paint_text_rects {\n                    let rect = text_shape.galley.rect.translate(text_shape.pos.to_vec2());\n                    self.tessellate_rect(\n                        &RectShape::stroke(rect, 2.0, (0.5, Color32::GREEN), StrokeKind::Outside),\n                        out,\n                    );\n                }\n                self.tessellate_text(&text_shape, out);\n            }\n            Shape::QuadraticBezier(quadratic_shape) => {\n                self.tessellate_quadratic_bezier(&quadratic_shape, out);\n            }\n            Shape::CubicBezier(cubic_shape) => self.tessellate_cubic_bezier(&cubic_shape, out),\n            Shape::Callback(_) => {\n                panic!(\"Shape::Callback passed to Tessellator\");\n            }\n        }\n    }\n\n    /// Tessellate a single [`CircleShape`] into a [`Mesh`].\n    ///\n    /// * `shape`: the circle to tessellate.\n    /// * `out`: triangles are appended to this.\n    pub fn tessellate_circle(&mut self, shape: CircleShape, out: &mut Mesh) {\n        let CircleShape {\n            center,\n            radius,\n            mut fill,\n            stroke,\n        } = shape;\n\n        if radius <= 0.0 {\n            return;","sourceCodeStart":1452,"sourceCodeEnd":1488,"githubUrl":"https://github.com/emilk/egui/blob/441971a776322a482e371775219380eca812cfa9/crates/epaint/src/tessellator.rs#L1452-L1488","documentation":"This panic fires when a `Shape::Callback` variant is handed to the `Tessellator`. Callback shapes are special: they are executed by the painter/render pipeline with direct access to the callback context, and cannot be converted into triangles by the tessellator. The library treats this as an unreachable internal state and panics deliberately.","triggerScenarios":"Calling `tessellate_shape` (directly or via `tessellate_clipped_shape`) on a `Shape::Callback(...)`. This happens if callback shapes are not filtered out before tessellation, e.g. by custom rendering code that collects all shapes from a `Shape` list and tessellates them indiscriminately.","commonSituations":"Custom renderers or screenshot/texture dumping code that iterate `paint_output.shapes` and tessellate every shape, forgetting that callbacks are not tessellable. Also occurs when cloning/reordering shapes and accidentally routing a callback shape into a tessellation pass.","solutions":["Filter out `Shape::Callback` before tessellating: iterate shapes and match `Shape::Callback(cb) => cb.call(ctx)` separately, tessellating only mesh/text shapes.","If you need the callback's pixels, execute the callback first (giving it a Painter) and then tessellate the shapes it produces.","Check whether your egui version moved callback handling into the renderer (e.g. `Renderer::paint` handles callbacks); update integration code to not tessellate raw shape lists containing callbacks."],"exampleFix":"// before\nfor shape in shapes {\n    tessellator.tessellate_shape(shape, &mut out);\n}\n// after\nfor shape in shapes {\n    match &shape {\n        Shape::Callback(_) => { /* execute callback via renderer instead */ }\n        _ => tessellator.tessellate_shape(shape, &mut out),\n    }\n}","handlingStrategy":"type-guard","validationCode":"// Rust: filter callback shapes before tessellation\nlet tessellatable: Vec<&Shape> = shapes.iter().filter(|s| !matches!(s, Shape::Callback(_))).collect();","typeGuard":"fn is_tessellatable(shape: &Shape) -> bool {\n    !matches!(shape, Shape::Callback(_))\n}","tryCatchPattern":"// Rust: this is a panic, not a Result; guard at call site instead\nif matches!(shape, Shape::Callback(_)) {\n    // route to renderer callback path, never to tessellator\n} else {\n    tessellator.tessellate_shape(shape, &mut out);\n}","preventionTips":["Never write a loop that tessellates every `Shape` without matching on the variant first.","Route `Shape::Callback` to the renderer (which executes it), not the tessellator.","When writing screenshot/export code, explicitly document how callbacks are skipped or executed."],"tags":["panic","rendering","tessellation","rust"],"backgroundTag":"unsupported-operation","analyzedSha":"441971a776322a482e371775219380eca812cfa9","analyzedAt":"2026-09-12T04:29:21.500Z","contentChangedAt":"2026-09-12T04:29:21.500Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}