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

  1. Transcode VP8 sources to H.264/VP9 before thumbnail extraction.
  2. Detect VP8 + CrOS at the app level and skip the Glide video load, using a poster image instead.
  3. 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

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


AI-assisted analysis of bumptech/glide@eb14a895d8 (2026-08-14). Data as JSON: /api/errors/5af4cd8aeeee5572. Report an issue: GitHub.