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
- Check resource.exists() and resource.isReadable() before creating/reading
- Read bytes yourself with explicit IOException handling and wrap in a ByteArrayResource
- Catch RuntimeException and inspect getCause() for the root IOException
- 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
- Check exists()/isReadable() before constructing TextReader
- Copy remote/unstable sources to local temp files first
- Specify an explicit Charset when the source encoding is uncertain
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
- Error reading JSON resource
- Failed to get index size for session:
- IOException (wrapped RuntimeException)
- Could not read content length
- Could not read content length
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)