spring-projects/spring-ai · error · IllegalArgumentException

Line length cannot be negative

Error message

Line length cannot be negative

What it means

TextLine's package constructor validates the computed line length before allocating its char buffer. A negative lineLength means upstream PDF layout math produced an invalid (negative) width/position delta, so an IllegalArgumentException is thrown instead of allocating a broken array.

Source

Thrown at document-readers/spring-ai-pdf-document-reader/src/main/java/org/springframework/ai/reader/pdf/layout/TextLine.java:38

/*
 * @author Soby Chacko
 * @author Tibor Tarnai
 */

class TextLine {

	private static final char SPACE_CHARACTER = ' ';

	private final int lineLength;

	private final char[] line;

	private int lastIndex;

	TextLine(int lineLength) {
		if (lineLength < 0) {
			throw new IllegalArgumentException("Line length cannot be negative");
		}
		else if (lineLength > 14_400) {
			// Cap to a reasonable limit to prevent attack via excessive char allocation
			// below.
			// 14_400 pdf units is the recommendation for the max dimension of a page by
			// ISO 32000
			throw new IllegalArgumentException("Unreasonable lineLength of %d provided".formatted(lineLength));
		}
		this.lineLength = lineLength / ForkPDFLayoutTextStripper.OUTPUT_SPACE_CHARACTER_WIDTH_IN_PT;
		this.line = new char[this.lineLength];
		Arrays.fill(this.line, SPACE_CHARACTER);
	}

	public void writeCharacterAtIndex(final Character character) {
		character.setIndex(this.computeIndexForCharacter(character));
		int index = character.getIndex();
		char characterValue = character.getCharacterValue();
		if (this.indexIsInBounds(index) && this.line[index] == SPACE_CHARACTER) {

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Sanitize the PDF (qpdf --clean / ghostscript rewrite) to fix invalid text positioning before extraction.
  2. Disable layout-aware extraction (use plain text extraction) to bypass TextLine construction.
  3. Catch IllegalArgumentException from DocumentReader.get() and skip the offending file.
  4. Report/fix the upstream coordinate computation if it comes from your own PDF-generating code.

Example fix

// before
List<Document> docs = new PagePdfDocumentReader(badResource,
    PagePdfDocumentReader.config().withLayoutEnabled()).get();

// after
List<Document> docs;
try {
    docs = new PagePdfDocumentReader(badResource,
        PagePdfDocumentReader.config().withLayoutEnabled()).get();
} catch (IllegalArgumentException e) {
    docs = List.of(); // or fall back to non-layout extraction
}
Defensive patterns

Strategy: validation

Validate before calling

try (PDDocument doc = Loader.loadPDF(file)) {
    for (PDPage page : doc.getPages()) {
        PDRectangle mb = page.getMediaBox();
        if (mb.getWidth() < 0 || mb.getHeight() < 0)
            throw new IllegalArgumentException("negative page dimension: " + mb);
    }
}

Try / catch

try {
    List<Document> docs = new PagePdfDocumentReader(resource,
        PagePdfDocumentReader.config().withLayoutEnabled()).get();
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("Line length cannot be negative")) {
        log.warn("Skipping PDF with invalid text geometry: {}", resource);
        docs = List.of();
    } else throw e;
}

Prevention

When it happens

Trigger: PDF text extraction where a computed line length from text positions (e.g. negative x-position deltas or negative scaling in text matrices) yields a value < 0 passed to the TextLine constructor during writeTextPositionList processing.

Common situations: Malformed PDFs with negative coordinates or bad transformation matrices; files generated by buggy producers; fuzzed/adversarial inputs to ForkPDFLayoutTextStripper.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/b5c73e31c56fabd5. Report an issue: GitHub.