{"record":{"id":"8516fc860ae5af0b","repo":"spring-projects/spring-ai","slug":"unsupported-media-data-type-expected-byte-or","errorCode":null,"errorMessage":"Unsupported media data type: . Expected byte[] or String.","messagePattern":"Unsupported media data type: \\. Expected byte\\[\\] or String\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java","lineNumber":1405,"sourceCode":"\tprivate boolean isPdfMedia(MimeType mimeType) {\n\t\treturn \"application\".equals(mimeType.getType()) && \"pdf\".equals(mimeType.getSubtype());\n\t}\n\n\t/**\n\t * Extracts media data as a string. Converts byte[] to base64, passes through URL\n\t * strings.\n\t * @param mediaData the media data (byte[] or String)\n\t * @return base64-encoded string or URL string\n\t * @throws IllegalArgumentException if data type is unsupported\n\t */\n\tprivate String fromMediaData(Object mediaData) {\n\t\tif (mediaData instanceof byte[] bytes) {\n\t\t\treturn Base64.getEncoder().encodeToString(bytes);\n\t\t}\n\t\telse if (mediaData instanceof String text) {\n\t\t\treturn text;\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Unsupported media data type: \" + mediaData.getClass().getSimpleName()\n\t\t\t\t+ \". Expected byte[] or String.\");\n\t}\n\n\t/**\n\t * Creates an {@link ImageBlockParam} from the given MIME type and data.\n\t * @param mimeType the image MIME type (image/png, image/jpeg, etc.)\n\t * @param data base64-encoded image data or HTTPS URL\n\t * @return the ImageBlockParam wrapped in ContentBlockParam\n\t */\n\tprivate ContentBlockParam createImageBlockParam(MimeType mimeType, String data) {\n\t\tImageBlockParam.Source source;\n\t\tif (data.startsWith(\"https://\")) {\n\t\t\tsource = ImageBlockParam.Source.ofUrl(UrlImageSource.builder().url(data).build());\n\t\t}\n\t\telse {\n\t\t\tsource = ImageBlockParam.Source\n\t\t\t\t.ofBase64(Base64ImageSource.builder().data(data).mediaType(toSdkImageMediaType(mimeType)).build());\n\t\t}","sourceCodeStart":1387,"sourceCodeEnd":1423,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java#L1387-L1423","documentation":"AnthropicChatModel's media-data extraction accepts only byte[] (Base64-encoded) and String (passed through as-is) as the data payload of a Media. Any other object type (InputStream, Resource, ByteBuffer, byte wrapper, etc.) reaches the final throw. The library cannot know how to serialize arbitrary types into an Anthropic block, so it fails fast with IllegalArgumentException.","triggerScenarios":"Constructing Media with a payload that is not byte[] or String, e.g. new Media(mimeType, inputStream), new Media(mimeType, resource), a ByteBuffer, or a Media created by another integration (e.g. OpenAI module) that allows Resource payloads, then sending it through AnthropicChatModel.","commonSituations":"Reusing prompt-building code written for another Spring AI model (OpenAI accepts Resource); loading file content with Files.newInputStream and passing the stream directly; wrapping bytes in a custom DTO instead of raw byte[].","solutions":["Convert the payload to byte[] before creating the Media (e.g. resource.getContentAsByteArray() or stream.readAllBytes()).","For text media, pass the content as a String instead.","Fix the generic MIME-type/empty-message case by ensuring mediaData is non-null so getClass().getSimpleName() is meaningful; null data indicates an earlier construction bug.","Centralize a helper that normalizes Resource/InputStream inputs to byte[] for all Media construction in your codebase."],"exampleFix":"// before\nvar media = new Media(MimeType.valueOf(\"image/png\"), resource);\n// after\nvar media = new Media(MimeType.valueOf(\"image/png\"), resource.getContentAsByteArray());","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean isSupportedMediaData(Object data) {\n    return data instanceof byte[] || data instanceof String;\n}\n// guard before building Media:\n// if (!isSupportedMediaData(payload)) payload = toBytes(payload);","tryCatchPattern":"try {\n    return client.call(prompt);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Unsupported media data type\")) {\n        throw new IllegalStateException(\"Convert media payload to byte[] or String before sending to Anthropic\", e);\n    }\n    throw e;\n}","preventionTips":["Always pass byte[] (or String for text) as Media data in Anthropic-bound prompts.","Use resource.getContentAsByteArray() for Resource inputs instead of the Resource itself.","Centralize Media creation in one helper so payload typing is enforced once."],"tags":["java","spring-ai","anthropic","type-mismatch","media"],"backgroundTag":"type-mismatch","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}