bumptech/glide · error · IllegalStateException
Cannot decode VP8 video on CrOS.
Error message
Cannot decode VP8 video on CrOS.
What it means
IllegalStateException thrown by VideoDecoder.decodeFrame() when isUnsupportedFormat() detects a VP8 video being decoded on ChromeOS (CrOS). On ChromeOS, Android's MediaMetadataRetriever cannot decode VP8, so Glide fails fast instead of returning a blank frame.
Source
Thrown at library/src/main/java/com/bumptech/glide/load/resource/bitmap/VideoDecoder.java:223
} else {
mediaMetadataRetriever.release();
}
}
return BitmapResource.obtain(result, bitmapPool);
}
@Nullable
private Bitmap decodeFrame(
@NonNull T resource,
MediaMetadataRetriever mediaMetadataRetriever,
long frameTimeMicros,
int frameOption,
int outWidth,
int outHeight,
DownsampleStrategy strategy) {
if (isUnsupportedFormat(resource, mediaMetadataRetriever)) {
throw new IllegalStateException("Cannot decode VP8 video on CrOS.");
}
Bitmap result = null;
// Arguably we should handle the case where just width or just height is set to
// Target.SIZE_ORIGINAL. Up to and including OMR1, MediaMetadataRetriever defaults to setting
// the dimensions to the display width and height if they aren't specified (ie
// getScaledFrameAtTime is not used). Given that this is an optimization only if
// Target.SIZE_ORIGINAL is not used and not using getScaledFrameAtTime ever would match the
// behavior of Glide in all versions of Android prior to OMR1, it's probably fine for now.
if (Build.VERSION.SDK_INT >= VERSION_CODES.O_MR1
&& outWidth != Target.SIZE_ORIGINAL
&& outHeight != Target.SIZE_ORIGINAL
&& strategy != DownsampleStrategy.NONE) {
result =
decodeScaledFrame(
mediaMetadataRetriever, frameTimeMicros, frameOption, outWidth, outHeight, strategy);
}
View on GitHub (pinned to eb14a895d8)
Solutions
- Transcode VP8 sources to H.264/VP9 before thumbnail extraction.
- Detect VP8 + CrOS at the app level and skip the Glide video load, using a poster image instead.
- Catch the IllegalStateException and fall back to a static placeholder.
Example fix
// before
Glide.with(ctx).asBitmap().load(uri).into(img);
// after
try {
Glide.with(ctx).asBitmap().load(uri).into(img);
} catch (IllegalStateException e) {
img.setImageResource(R.drawable.video_placeholder);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Detect ChromeOS and VP8 before loading.
boolean isCros = "cros".equals(Build.DEVICE) || isCrOs();
boolean isVp8 = "video/x-vnd.on2.vp8".equals(mimeType);
if (isCros && isVp8) { /* use poster, skip video load */ } Try / catch
try { Glide.with(ctx).asBitmap().load(uri).into(img); }
catch (IllegalStateException e) {
if ("Cannot decode VP8 video on CrOS.".equals(e.getMessage())) {
img.setImageResource(R.drawable.video_placeholder);
} else throw e;
} Prevention
- Transcode VP8 sources to H.264 before thumbnailing.
- Skip Glide video loads on CrOS for VP8 inputs.
- Provide a static poster fallback for video thumbnails.
When it happens
Trigger: Calling Glide.with(...).asBitmap().load(vp8VideoUri) on a ChromeOS device (or ChromeOS-flavored Android runtime). The format detection in isUnsupportedFormat returns true for VP8 on CrOS.
Common situations: Apps running on Chromebooks / CrOS that load VP8 video thumbnails. CI tests on CrOS-based emulators. Apps that accept arbitrary user-uploaded videos including VP8.
Related errors
- Requested frame must be non-negative, or DEFAULT_FRAME, give
- Cannot apply transformation on width: {outWidth} or height:
- Cannot scale with factor: {exactScaleFactor} from: {downsamp
- Cannot round with null rounding
- Unable to convert {drawable} to a Bitmap
AI-assisted analysis of bumptech/glide@eb14a895d8 (2026-08-14).
Data as JSON: /api/errors/5af4cd8aeeee5572.
Report an issue: GitHub.