{"record":{"id":"1b64e4f924b25cc7","repo":"iced-rs/iced","slug":"line-must-be-parsed","errorCode":null,"errorMessage":"Line must be parsed","messagePattern":"Line must be parsed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"widget/src/markdown.rs","lineNumber":1857,"sourceCode":"                            text: text[range].to_owned(),\n                            code,\n                        });\n                    }\n\n                    if self.current + 1 == self.lines.len() {\n                        let _ = self.lines.pop();\n                    }\n\n                    self.lines.push((text.to_owned(), spans));\n                }\n            }\n\n            self.current += 1;\n\n            &self\n                .lines\n                .get(self.current - 1)\n                .expect(\"Line must be parsed\")\n                .1\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    fn groups<const N: usize>(items: &[Item]) -> [(Option<&Item>, &[Item]); N] {\n        sections(items)\n            .collect::<Vec<_>>()\n            .try_into()\n            .expect(\"Unexpected number of sections\")\n    }\n\n    fn assert_same_items<'a>(\n        left: impl IntoIterator<Item = &'a Item>,","sourceCodeStart":1839,"sourceCodeEnd":1875,"githubUrl":"https://github.com/iced-rs/iced/blob/d146509d893945de5c304cfaf4301335eee278bd/widget/src/markdown.rs#L1839-L1875","documentation":"The markdown parser's line iterator asserts that lines.get(self.current - 1) succeeds with expect(\"Line must be parsed\"). Since current was just incremented, the invariant is that the previous line always exists; a panic means the iterator advanced past the end or was constructed with lines that were never stored, i.e. an off-by-one or empty-lines bug in the parser state.","triggerScenarios":"Advancing the line cursor past the last line and then requesting the current line - typically from a parse routine that fails to check whether current exceeds lines.len() before calling the next-line accessor.","commonSituations":"Markdown input ending abruptly (file ends inside an open block like a code fence or list), causing the parser to peek one line too far; regression from a parser change to the cursor handling.","solutions":["Ensure input is well-formed and doesn't terminate inside an unclosed block; append a trailing newline to the markdown content before parsing.","Check the version of iced_widget - this is an internal invariant; upgrade if a fix for truncated-input handling exists.","If you embed iced's markdown parser, guard block parsers so they stop when current >= lines.len() instead of pulling the next line.","Minimize the failing input to isolate the truncated construct and fix or escape it."],"exampleFix":"// before\nlet line = self.lines.get(self.current - 1).expect(\"Line must be parsed\");\n// after (library-side hardening)\nlet line = match self.lines.get(self.current.checked_sub(1)?) { Some(l) => l, None => return None };","handlingStrategy":"validation","validationCode":"// ensure input ends cleanly before parsing\nlet md = if source.ends_with('\\n') { source.to_string() } else { format!(\"{source}\\n\") };","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always terminate markdown content with a trailing newline.","Avoid truncating streamed markdown before rendering; render only complete blocks.","Reproduce panics with minimal inputs and upgrade iced when fixed."],"tags":["markdown","parser","panic","index-out-of-bounds"],"backgroundTag":"index-out-of-bounds","analyzedSha":"d146509d893945de5c304cfaf4301335eee278bd","analyzedAt":"2026-09-11T16:54:14.229Z","contentChangedAt":"2026-09-11T16:54:14.229Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}