spring-projects/spring-ai · error · IllegalArgumentException
Invalid video content type:
Error message
Invalid video content type:
What it means
BedrockProxyChatModel.mapMediaToContentBlock converts Media for video content into a Bedrock VideoBlock. Video data must arrive as a supported content representation (e.g. byte[]/Resource with a known MIME type); when media.getData() is of a class the mapper cannot turn into a video source, it throws IllegalArgumentException 'Invalid video content type: ' + the data class.
Source
Thrown at models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java:523
VideoSource videoSource = null;
if (media.getData() instanceof byte[] bytes) {
videoSource = VideoSource.builder().bytes(SdkBytes.fromByteArrayUnsafe(bytes)).build();
}
else if (media.getData() instanceof String uriText) {
videoSource = VideoSource.builder().s3Location(S3Location.builder().uri(uriText).build()).build();
}
else if (media.getData() instanceof URL url) {
try {
videoSource = VideoSource.builder()
.s3Location(S3Location.builder().uri(url.toURI().toString()).build())
.build();
}
catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
}
}
else {
throw new IllegalArgumentException("Invalid video content type: " + media.getData().getClass());
}
return ContentBlock.fromVideo(VideoBlock.builder().source(videoSource).format(videoFormat).build());
}
else if (BedrockMediaFormat.isSupportedImageFormat(mimeType)) { // Image
ImageSource.Builder sourceBuilder = ImageSource.builder();
if (media.getData() instanceof byte[] bytes) {
sourceBuilder.bytes(SdkBytes.fromByteArrayUnsafe(bytes)).build();
}
else if (media.getData() instanceof String text) {
if (text.startsWith("s3://")) {
sourceBuilder.s3Location(S3Location.builder().uri(text).build()).build();
}
else if (text.startsWith("http://") || text.startsWith("https://")) {
// Not base64
if (URLValidator.isValidURLStrict(text)) {
try {View on GitHub (pinned to 98a7beda4f)
Solutions
- Provide video content as byte[] or as a Resource so the mapper can build the VideoBlock source.
- Download the video bytes yourself and construct Media with the raw data plus the correct MIME type (e.g. video/mp4).
- Verify the MIME type/classification: if the content is actually an image or document, use the appropriate Media constructor so it routes to the right branch.
- Check the supported Bedrock video formats (mp4/mov/mkv/webm) and that your data matches one.
Example fix
// before
Media media = new Media(MimeTypeUtils.parseMimeType("video/mp4"), someUrlObject); // getData() class unsupported
// after
byte[] videoBytes = someUrlObject.openStream().readAllBytes();
Media media = new Media(MimeTypeUtils.parseMimeType("video/mp4"), videoBytes); Defensive patterns
Strategy: validation
Validate before calling
static void assertVideoMediaSupported(Media media) {
Object data = media.getData();
if (!(data instanceof byte[]) && !(data instanceof Resource)) {
throw new IllegalArgumentException("Video media data must be byte[] or Resource, got: "
+ (data == null ? "null" : data.getClass()));
}
} Type guard
static Optional<byte[]> asVideoBytes(Media media) {
Object d = media.getData();
if (d instanceof byte[] b) return Optional.of(b);
if (d instanceof Resource r) {
try { return Optional.of(r.getInputStream().readAllBytes()); }
catch (IOException e) { return Optional.empty(); }
}
return Optional.empty();
} Try / catch
try {
return bedrockModel.call(prompt);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Invalid video content type")) {
log.error("Rebuild video media with byte[]/Resource data: {}", e.getMessage());
}
throw e;
} Prevention
- Always pass video content as byte[] or Resource with an explicit video/* MIME type.
- Download remote video URLs to bytes before constructing Media.
- Use only Bedrock-supported video formats (mp4, mov, mkv, webm).
When it happens
Trigger: Building a UserMessage with Media whose getData() returns an unsupported object type (e.g. a URL wrapper or custom object instead of byte[]/Resource) while the media MIME type is classified as video; calling chat with video media built via an unsupported data holder.
Common situations: Passing remote video URLs as Media data when the mapper only accepts raw bytes/Resource for video; using a Media factory variant that stores data as a generic object; tests that throw with loopback/FTP/IMDS URLs to verify URL fetching is blocked.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Unsupported message type:
- Invalid Image content type:
- Unsupported media format:
- Unsupported media format:
- Media URL response exceeds maximum allowed size of bytes
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/71e41d08ac9a5365.
Report an issue: GitHub.