spring-projects/spring-ai · warning
Skipping paragraph titled '<title>' because it has an invali
Error message
Skipping paragraph titled '<title>' because it has an invalid start page number: <pageNumber>
What it means
The PDF paragraph reader (PDFBox-based TOC/paragraph extraction) encountered a paragraph whose start page number is less than 1, i.e. invalid for a 1-indexed PDF page model. Instead of failing, it skips the paragraph, logs this warning, and returns an empty string for the text range, so that paragraph's content is silently missing from the extracted document.
Source
Thrown at document-readers/spring-ai-pdf-document-reader/src/main/java/org/springframework/ai/reader/pdf/ParagraphPdfDocumentReader.java:181
return document;
}
protected void addMetadata(Paragraph from, Paragraph to, Document document) {
document.getMetadata().put(METADATA_TITLE, from.title());
document.getMetadata().put(METADATA_START_PAGE, from.startPageNumber());
document.getMetadata().put(METADATA_END_PAGE, from.endPageNumber());
document.getMetadata().put(METADATA_LEVEL, from.level());
if (this.resourceFileName != null) {
document.getMetadata().put(METADATA_FILE_NAME, this.resourceFileName);
}
}
public String getTextBetweenParagraphs(Paragraph fromParagraph, Paragraph toParagraph) {
if (fromParagraph.startPageNumber() < 1) {
if (logger.isWarnEnabled()) {
logger.warn("Skipping paragraph titled '" + fromParagraph.title()
+ "' because it has an invalid start page number: " + fromParagraph.startPageNumber());
}
return "";
}
// Page started from index 0, while PDFBOx getPage return them from index 1.
int startPage = fromParagraph.startPageNumber() - 1;
int endPage = toParagraph.startPageNumber() - 1;
if (fromParagraph == toParagraph || endPage < startPage) {
endPage = startPage;
}
try {
StringBuilder sb = new StringBuilder();
var pdfTextStripper = new PDFLayoutTextStripperByArea();View on GitHub (pinned to 98a7beda4f)
Solutions
- Inspect the PDF's outline/bookmarks with a PDF inspector and repair or regenerate the source PDF.
- Fall back to PagePdfDocumentReader, which reads by explicit page ranges and ignores the TOC structure.
- Pre-validate the extracted paragraphs and filter out ones with startPageNumber < 1 before calling getTextBetweenParagraphs.
- If the paragraph content matters, extract its text via an alternate path (e.g. PDFTextStripper over the whole document) and match by title.
Example fix
// before: unguarded extraction
String text = reader.getTextBetweenParagraphs(from, to);
// after: validate first
if (from.startPageNumber() >= 1) {
String text = reader.getTextBetweenParagraphs(from, to);
} else {
logger.warn("Skipping invalid paragraph: " + from.title());
} Defensive patterns
Strategy: fallback
Validate before calling
if (paragraph.startPageNumber() < 1) {
logger.warn("Invalid paragraph '" + paragraph.title() + "', skipping");
return "";
} Type guard
boolean hasValidPageRange(Paragraph p) {
return p != null && p.startPageNumber() >= 1;
} Try / catch
// getTextBetweenParagraphs does not throw; check for empty result
String text = reader.getTextBetweenParagraphs(from, to);
if (text.isEmpty()) {
// fall back to whole-document extraction by page range
text = pageReader.get(p1, p2);
} Prevention
- Validate PDF outlines before using ParagraphPdfDocumentReader.
- Prefer PagePdfDocumentReader for PDFs with unreliable bookmarks.
- Log which paragraph titles were skipped so missing content is noticed.
- Test your reader against the actual PDF corpus you will ingest.
When it happens
Trigger: Calling getTextBetweenParagraphs (via docText) on a Paragraph whose startPageNumber() returns 0 or negative — typically a malformed or synthetic Paragraph produced by parsing an unusual PDF outline/TOC (e.g. page labels that don't resolve to real pages).
Common situations: Reading PDFs with non-standard or corrupted bookmarks/TOC structures; PDFs produced by generators that emit bogus page references in the document outline; relying on ParagraphPdfDocumentReader where the PDF's logical structure does not match physical pages.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Unreasonable pdf paragraph depth
- pdf containing circular reference or unreasonable nesting le
- Unreasonable number of lines (%d) computed from content of p
- Line length cannot be negative
- Unreasonable lineLength of %d provided
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/01347dbabd5d3d60.
Report an issue: GitHub.