{"record":{"id":"395f0435a3f3b6f3","repo":"spring-projects/spring-ai","slug":"unsupported-media-data-type-395f04","errorCode":null,"errorMessage":"Unsupported media data type: ","messagePattern":"Unsupported media data type: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatModel.java","lineNumber":996,"sourceCode":"\tprivate String fromAudioData(Object audioData) {\n\t\tif (audioData instanceof byte[] bytes) {\n\t\t\treturn Base64.getEncoder().encodeToString(bytes);\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Unsupported audio data type: \" + audioData.getClass().getSimpleName());\n\t}\n\n\tprivate String fromMediaData(org.springframework.util.MimeType mimeType, Object mediaContentData) {\n\t\tif (mediaContentData instanceof byte[] bytes) {\n\t\t\t// Assume the bytes are an image. So, convert the bytes to a base64 encoded\n\t\t\t// following the prefix pattern.\n\t\t\treturn String.format(\"data:%s;base64,%s\", mimeType.toString(), Base64.getEncoder().encodeToString(bytes));\n\t\t}\n\t\telse if (mediaContentData instanceof String text) {\n\t\t\t// Assume the text is a URLs or a base64 encoded image prefixed by the user.\n\t\t\treturn text;\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Unsupported media data type: \" + mediaContentData.getClass().getSimpleName());\n\t\t}\n\t}\n\n\tprivate List<ChatCompletionTool> getChatCompletionTools(List<ToolDefinition> toolDefinitions,\n\t\t\t@Nullable OpenAiChatOptions requestOptions) {\n\t\treturn toolDefinitions.stream().map(toolDefinition -> {\n\t\t\tFunctionParameters.Builder parametersBuilder = FunctionParameters.builder();\n\t\t\t// Defaults to false: OpenAI's strict mode requires every schema property to\n\t\t\t// appear in \"required\" (optionality is expressed via nullable types, not\n\t\t\t// omission), which JsonSchemaGenerator does not produce by default. When a\n\t\t\t// caller opts in via OpenAiChatOptions#strict, applyStrictModeRequirements\n\t\t\t// below rewrites the schema to satisfy that contract.\n\t\t\tBoolean strictMode = false;\n\t\t\tif (requestOptions != null && requestOptions.getStrict() != null) {\n\t\t\t\tstrictMode = requestOptions.getStrict();\n\t\t\t}\n\t\t\telse if (this.options != null && this.options.getStrict() != null) {","sourceCodeStart":978,"sourceCodeEnd":1014,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatModel.java#L978-L1014","documentation":"OpenAiChatModel.fromMediaData accepts image/media content only as byte[] (encoded to a data URL) or as a String that is already a URL or user-supplied base64 payload. Any other type throws this IllegalArgumentException with the simple class name of the offending object.","triggerScenarios":"Passing a Media content object whose data is neither byte[] nor String (e.g. URI, URL, Path, InputStream) into OpenAiChatModel.call, reaching OpenAiChatModel.java:996.","commonSituations":"Passing a java.net.URL or Path object because it 'looks like a URL', or an InputStream from a downloaded image, instead of bytes or a URL string.","solutions":["Convert the object to byte[] (read the resource) or to its URL as a String (url.toString()) before constructing the Media.","If the data is a Path/File, use Files.readAllBytes(path) to pass bytes.","Check the actual runtime class named in the message and add an explicit conversion for it."],"exampleFix":"// before\nvar media = new Media(MimeTypeUtils.IMAGE_PNG, new URI(urlString));\n// after\nvar media = new Media(MimeTypeUtils.IMAGE_PNG, urlString);","handlingStrategy":"type-guard","validationCode":"if (!(mediaData instanceof byte[]) && !(mediaData instanceof String)) {\n    throw new IllegalArgumentException(\"Media data must be byte[] or String (URL/base64), got: \" + mediaData.getClass().getSimpleName());\n}","typeGuard":"static boolean isSupportedMediaData(Object data) {\n    return data instanceof byte[] || data instanceof String;\n}","tryCatchPattern":"try {\n    response = chatModel.call(prompt);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unsupported media data type\")) {\n        throw new InvalidMediaContentException(\"Use byte[] or a URL/base64 String for media content\", e);\n    }\n    throw e;\n}","preventionTips":["Never pass URI/URL/Path/InputStream objects as media data","Convert Paths with Files.readAllBytes and URLs with toString()","Wrap media construction in a helper that narrows types first"],"tags":["illegal-argument","media","type-mismatch"],"backgroundTag":"type-mismatch","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"}