{"record":{"id":"00f001fbad7d6346","repo":"spring-projects/spring-ai","slug":"java-io-ioexception-00f001","errorCode":null,"errorMessage":"java.io.IOException","messagePattern":"java\\.io\\.IOException","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-commons/src/main/java/org/springframework/ai/content/Media.java","lineNumber":136,"sourceCode":"\t}\n\n\t/**\n\t * Create a new Media instance.\n\t * @param mimeType the media MIME type\n\t * @param resource the media resource\n\t */\n\tpublic Media(MimeType mimeType, Resource resource) {\n\t\tAssert.notNull(mimeType, \"MimeType must not be null\");\n\t\tAssert.notNull(resource, \"Data must not be null\");\n\t\ttry {\n\t\t\tbyte[] bytes = resource.getContentAsByteArray();\n\t\t\tthis.mimeType = mimeType;\n\t\t\tthis.id = null;\n\t\t\tthis.data = bytes;\n\t\t\tthis.name = generateDefaultName(mimeType);\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new Media builder.\n\t * @return a new Media builder instance\n\t */\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\t/**\n\t * Create a new Media instance.\n\t * @param mimeType the media MIME type\n\t * @param data the media data\n\t * @param id the media id\n\t */\n\tprivate Media(MimeType mimeType, Object data, @Nullable String id, @Nullable String name) {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-commons/src/main/java/org/springframework/ai/content/Media.java#L118-L154","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":"// before\nMedia media = new Media(MimeTypeUtils.IMAGE_PNG, new URL(\"http://localhost:8080/img.png\"));\n// after\nbyte[] bytes = download(new URL(\"http://localhost:8080/img.png\")); // handle IOException explicitly\nMedia media = new Media(MimeTypeUtils.IMAGE_PNG, bytes);","handlingStrategy":"try-catch","validationCode":"URL url = new URL(mediaUrl);\ntry (InputStream in = url.openStream()) { /* readable check */ }","typeGuard":null,"tryCatchPattern":"try {\n    Media m = new Media(mimeType, url);\n} catch (RuntimeException e) {\n    // getCause() is the IOException from URL fetch; log url and fall back to placeholder media\n}","preventionTips":["Prefer builder data(Resource)/data(byte[]) over URL-based constructors","Health-check media URLs at startup","Keep a local cache of media bytes"],"tags":["io","url","media"],"backgroundTag":"file-read-failed","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}