spring-projects / spring-projects/spring-ai

`TikaDocumentReader` repeats previous text when `get()` is called more than once

Open
#6,806 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage
Dominant language
Java
Stars
9.5k
Forks
2.9k
Avg merge
1d 7h
Merged PRs (30d)
6

Description

Bug description

TikaDocumentReader keeps its ContentHandler in a final field built once by the constructor, and get() parses into that same handler on every call. BodyContentHandler accumulates and nothing resets it, so a second get() returns the first extraction followed by the second. The Metadata field is shared the same way.

Whether this counts as a defect depends on whether the reader is meant to be used more than once, and that is what I would like to settle.

Arguments that repeated calls should work: DocumentReader extends Supplier<List<Document>>, and the sibling readers are safe to call again. TextReader and JsonReader re-read the resource on each call, and MarkdownDocumentReader builds a new DocumentVisitor per read. TikaDocumentReader is the one that keeps its accumulator in a field.

Argument the other way: the reference documentation example builds a new reader inside the method that reads, so following the docs you never reach this. Nothing states that the reader is single use either.

If single use is intended, saying so on the class would be enough. If repeated calls are meant to work, the handler and the metadata need to be per call. One thing to note for that path: the public constructor that takes a ContentHandler hands ownership to the caller, so an injected handler probably cannot be recreated.

Environment

Spring AI main at c988e72. The same code is on 1.1.x and 1.0.x, under document-readers/tika-reader.
Java 17.0.19. No vector store involved.

Steps to reproduce

Build a TikaDocumentReader over any supported document and call get() twice.

Expected behavior

The second call returns the same text as the first.

What happens instead: the second call returns the first text with the same text appended. Using word-sample.docx from the module test resources, the first call returns 9798 characters and the second returns 19596, and the second starts with the first.

Minimal Complete Reproducible example

Add to TikaDocumentReaderTests:

@Test
void secondReadRepeatsTheFirstExtraction() {
    var reader = new TikaDocumentReader("classpath:/word-sample.docx");

    String first = reader.get().get(0).getText();
    String second = reader.get().get(0).getText();

    assertThat(second).isEqualTo(first);
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with TikaDocumentReader in the document-readers/tika-reader module and run TikaDocumentReaderTests using word-sample.docx. Resolve whether DocumentReader instances must support repeated reads, including the constructor that accepts a ContentHandler, then make the chosen behavior explicit in tests and API documentation.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.