spring-projects/spring-ai · error · RuntimeException
java.io.IOException
Error message
java.io.IOException
What it means
Media's constructor reads bytes from a URL (via UrlUtils) to populate media data; if opening or reading that URL throws an IOException, it is wrapped and rethrown as a RuntimeException. This means constructing a Media with a URL-based source fails fast at object creation time rather than later during API calls.
Source
Thrown at spring-ai-commons/src/main/java/org/springframework/ai/content/Media.java:136
}
/**
* Create a new Media instance.
* @param mimeType the media MIME type
* @param resource the media resource
*/
public Media(MimeType mimeType, Resource resource) {
Assert.notNull(mimeType, "MimeType must not be null");
Assert.notNull(resource, "Data must not be null");
try {
byte[] bytes = resource.getContentAsByteArray();
this.mimeType = mimeType;
this.id = null;
this.data = bytes;
this.name = generateDefaultName(mimeType);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Creates a new Media builder.
* @return a new Media builder instance
*/
public static Builder builder() {
return new Builder();
}
/**
* Create a new Media instance.
* @param mimeType the media MIME type
* @param data the media data
* @param id the media id
*/
private Media(MimeType mimeType, Object data, @Nullable String id, @Nullable String name) {View on GitHub (pinned to 98a7beda4f)
Solutions
- Verify the URL is reachable (curl it) before constructing Media
- Prefer the Builder with data(Resource) or data(byte[]) so I/O is handled in a controlled place
- Download the bytes yourself and pass a byte[] to avoid constructor-time I/O
- Catch RuntimeException (not IOException) around Media construction since the checked exception is wrapped
Example fix
// before
Media media = new Media(MimeTypeUtils.IMAGE_PNG, new URL("http://localhost:8080/img.png"));
// after
byte[] bytes = download(new URL("http://localhost:8080/img.png")); // handle IOException explicitly
Media media = new Media(MimeTypeUtils.IMAGE_PNG, bytes); Defensive patterns
Strategy: try-catch
Validate before calling
URL url = new URL(mediaUrl);
try (InputStream in = url.openStream()) { /* readable check */ } Try / catch
try {
Media m = new Media(mimeType, url);
} catch (RuntimeException e) {
// getCause() is the IOException from URL fetch; log url and fall back to placeholder media
} Prevention
- Prefer builder data(Resource)/data(byte[]) over URL-based constructors
- Health-check media URLs at startup
- Keep a local cache of media bytes
When it happens
Trigger: Calling the public Media constructor with a URL whose content cannot be fetched — unreachable host, HTTP error, malformed URL protocol, or connection reset — so resource.getContentAsByteArray()/URL openStream throws IOException.
Common situations: Pointing media at a localhost URL that isn't running, a URL behind auth, offline environments, or URLs with schemes the JDK URL handler doesn't support (e.g. custom classpath-style URIs).
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
- java.net.URISyntaxException
- Failed to create SSE transport for connection '<connectionNa
- Unsupported media data type: . Expected byte[] or String.
- Invalid filename for file '': must be a single path segment
- Invalid filename for file '': ''
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/00f001fbad7d6346.
Report an issue: GitHub.