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

  1. Verify the URL is reachable (curl it) before constructing Media
  2. Prefer the Builder with data(Resource) or data(byte[]) so I/O is handled in a controlled place
  3. Download the bytes yourself and pass a byte[] to avoid constructor-time I/O
  4. 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

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


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