{"record":{"id":"9ce33a4058600d57","repo":"zed-industries/zed","slug":"you-can-t-prepaint-linewithinvisibles-twice","errorCode":null,"errorMessage":"you can't prepaint LineWithInvisibles twice","messagePattern":"you can't prepaint LineWithInvisibles twice","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/editor/src/element.rs","lineNumber":7542,"sourceCode":"            line_elements,\n            window,\n            cx,\n        );\n    }\n\n    fn prepaint_with_custom_offset(\n        &mut self,\n        line_height: Pixels,\n        scroll_pixel_position: gpui::Point<ScrollPixelOffset>,\n        content_origin: gpui::Point<Pixels>,\n        line_y: Pixels,\n        line_elements: &mut SmallVec<[AnyElement; 1]>,\n        window: &mut Window,\n        cx: &mut App,\n    ) {\n        let mut fragment_origin =\n            content_origin + gpui::point(Pixels::from(-scroll_pixel_position.x), line_y);\n        for fragment in &mut self.fragments {\n            match fragment {\n                LineFragment::Text(line) => {\n                    fragment_origin.x += line.width;\n                }\n                LineFragment::Element { element, size, .. } => {\n                    let mut element = element\n                        .take()\n                        .expect(\"you can't prepaint LineWithInvisibles twice\");\n\n                    // Center the element vertically within the line.\n                    let mut element_origin = fragment_origin;\n                    element_origin.y += (line_height - size.height) / 2.;\n                    element.prepaint_at(element_origin, window, cx);\n                    line_elements.push(element);\n\n                    fragment_origin.x += size.width;\n                }\n            }","sourceCodeStart":7524,"sourceCodeEnd":7560,"githubUrl":"https://github.com/zed-industries/zed/blob/9d272b036335401f339d024ea94968fd51016c40/crates/editor/src/element.rs#L7524-L7560","documentation":"A one-shot lifecycle invariant: LineWithInvisibles::prepaint computes and caches per-line layout state, and painting a line prepaints it exactly once per frame. The expect fires when the same LineWithInvisibles element is prepainted twice — usually an element was reused across two paint passes or added to two parents — indicating a framework usage bug rather than bad data.","triggerScenarios":"Thrown at crates/editor/src/element.rs:7440 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Construct a fresh LineWithInvisibles per prepaint site instead of reusing a prepared element","Track a 'prepainted' flag and no-op (or rebuild) on a second prepaint rather than panicking","Audit callers that clone or re-add prepared line elements to multiple element trees"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"9d272b036335401f339d024ea94968fd51016c40","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}