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

  1. Provide video content as byte[] or as a Resource so the mapper can build the VideoBlock source.
  2. Download the video bytes yourself and construct Media with the raw data plus the correct MIME type (e.g. video/mp4).
  3. 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.
  4. 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

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


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