{"record":{"id":"23d4c70ae1bef981","repo":"rust-lang/mdBook","slug":"suffix-chapters-cannot-be-followed-by-a-list","errorCode":null,"errorMessage":"Suffix chapters cannot be followed by a list","messagePattern":"Suffix chapters cannot be followed by a list","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mdbook-summary/src/lib.rs","lineNumber":316,"sourceCode":"            if is_prefix { \"prefix\" } else { \"suffix\" }\n        );\n\n        loop {\n            match self.next_event() {\n                Some(ev @ Event::Start(Tag::List(..)))\n                | Some(\n                    ev @ Event::Start(Tag::Heading {\n                        level: HeadingLevel::H1,\n                        ..\n                    }),\n                ) => {\n                    if is_prefix {\n                        // we've finished prefix chapters and are at the start\n                        // of the numbered section.\n                        self.back(ev);\n                        break;\n                    } else {\n                        bail!(self.parse_error(\"Suffix chapters cannot be followed by a list\"));\n                    }\n                }\n                Some(Event::Start(Tag::Link { dest_url, .. })) => {\n                    let link = self.parse_link(dest_url.to_string());\n                    items.push(SummaryItem::Link(link));\n                }\n                Some(Event::Rule) => items.push(SummaryItem::Separator),\n                Some(_) => {}\n                None => break,\n            }\n        }\n\n        Ok(items)\n    }\n\n    fn parse_parts(&mut self) -> Result<Vec<SummaryItem>> {\n        let mut parts = vec![];\n","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/rust-lang/mdBook/blob/dc21064fc21d955a0e1f67e65e336883c3e5260b/crates/mdbook-summary/src/lib.rs#L298-L334","documentation":"SUMMARY.md structure must be: optional prefix chapters, then the numbered list, then optional suffix (affix) chapters. parse_affix handles the tail; if, while parsing suffix chapters, it encounters a new list start after suffix links have begun, the document is malformed and the parser raises this error.","triggerScenarios":"In SUMMARY.md, after the numbered list, one or more standalone suffix chapter links appear, followed by another Markdown list (e.g. a second numbered list or bullet list) — an Event::List arrives while is_prefix is false.","commonSituations":"Writing two numbered sections separated by suffix links; accidentally indenting later chapters so they form a new list; legacy SUMMARY layouts mixing affix chapters between lists.","solutions":["Move the stray list's chapters into the single numbered list or the prefix section of SUMMARY.md.","Convert the suffix links into part of the main numbered list if they should be numbered.","Remove the second list entirely; mdBook supports only prefix chapters, one numbered list, then suffix chapters."],"exampleFix":"<!-- before: SUMMARY.md -->\n- [Suffix](suffix.md)\n\n# Summary\n\n- [Chapter 1](ch1.md)\n- [Other](other.md)\n\n<!-- after -->\n# Summary\n\n- [Chapter 1](ch1.md)\n- [Other](other.md)\n\n- [Suffix](suffix.md)","handlingStrategy":"validation","validationCode":"// Reject SUMMARY.md with suffix links followed by another list\nconst lines = summary.split('\\n');\nlet seenNumbered = false, seenSuffix = false;\nfor (const line of lines) {\n  if (/^- \\[/.test(line) && seenNumbered && !/^\\s{2,}/.test(line)) seenSuffix = true;\n  else if (/^-\\s|^[0-9]+\\./.test(line) && seenSuffix) throw new Error('list after suffix chapters');\n  else if (/^[0-9]+\\. \\[/.test(line)) seenNumbered = true;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep SUMMARY.md layout strict: prefix links, one numbered list, then suffix links — nothing between lists.","Never start a new list after suffix chapters; merge those entries into the numbered list."],"tags":["summary","parse","structure","mdbook"],"backgroundTag":"malformed-summary-structure","analyzedSha":"dc21064fc21d955a0e1f67e65e336883c3e5260b","analyzedAt":"2026-09-01T10:15:12.134Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}