spring-projects/spring-ai · error · RuntimeException

IOException (wrapped RuntimeException)

Error message

IOException (wrapped RuntimeException)

What it means

TextReader.get() reads the resource's full text into a single Document; an IOException from the underlying stream is wrapped in a plain RuntimeException. The library treats an unreadable text source as fatal since producing the Document is the reader's whole purpose.

Solutions

  1. Check resource.exists() and resource.isReadable() before creating/reading
  2. Read bytes yourself with explicit IOException handling and wrap in a ByteArrayResource
  3. Catch RuntimeException and inspect getCause() for the root IOException
  4. Confirm charset assumptions; pass an explicit Charset to the TextReader constructor if needed

Example fix

// before
TextReader reader = new TextReader(new FileSystemResource(path));
Document doc = reader.get().get(0);
// after
Resource res = new FileSystemResource(path);
Assert.isTrue(res.exists() && res.isReadable(), "Cannot read text: " + path);
TextReader reader = new TextReader(res);
Document doc = reader.get().get(0);
Defensive patterns

Strategy: validation

Validate before calling

Assert.isTrue(resource.exists() && resource.isReadable(), "Cannot read text resource: " + resource.getDescription());

Try / catch

try {
    List<Document> docs = textReader.get();
} catch (RuntimeException e) {
    throw new IllegalStateException("Text read failed: " + resource, e.getCause());
}

Prevention

When it happens

Trigger: Calling textReader.get() where resource.getInputStream() throws — missing file, no read permission, character-stream decode failure, or remote resource I/O error.

Common situations: Wrong file path or classpath location, files deleted between listing and reading, unreadable encodings, or network-backed resources dropping connections.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at spring-ai-commons/src/main/java/org/springframework/ai/reader/TextReader.java:100

	public Map<String, Object> getCustomMetadata() {
		return this.customMetadata;
	}

	@Override
	public List<Document> get() {
		try (InputStream inputStream = this.resource.getInputStream()) {

			String document = StreamUtils.copyToString(inputStream, this.charset);

			// Inject source information as a metadata.
			this.customMetadata.put(CHARSET_METADATA, this.charset.name());
			this.customMetadata.put(SOURCE_METADATA, getResourceIdentifier(this.resource));

			return List.of(new Document(document, this.customMetadata));

		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	protected String getResourceIdentifier(Resource resource) {
		// Try to get the filename first
		String filename = resource.getFilename();
		if (filename != null && !filename.isEmpty()) {
			return filename;
		}

		// Try to get the URI
		try {
			URI uri = resource.getURI();
			return uri.toString();
		}
		catch (IOException ignored) {
			// If getURI() throws an exception, we'll try the next method
		}

View on GitHub (pinned to 98a7beda4f)