bumptech/glide · error · IOException

Received unexpected drawable type for animated image, failin

Error message

Received unexpected drawable type for animated image, failing: {decoded}

What it means

IOException thrown by AnimatedImageDecoder.decode() when ImageDecoder.decodeDrawable returns something other than AnimatedImageDrawable. The decoder only handles ANIMATED_WEBP (and ANIMATED_AVIF on API 31+); a non-animated result means the format classification was wrong or the platform returned a still frame.

Source

Thrown at library/src/main/java/com/bumptech/glide/load/resource/drawable/AnimatedImageDecoder.java:76

  @Synthetic
  boolean handles(InputStream is) throws IOException {
    return isHandled(ImageHeaderParserUtils.getType(imageHeaderParsers, is, arrayPool));
  }

  @SuppressWarnings("checkstyle:UnnecessaryParentheses") // Readability
  private boolean isHandled(ImageType imageType) {
    return imageType == ImageType.ANIMATED_WEBP
        || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && imageType == ImageType.ANIMATED_AVIF);
  }

  @Synthetic
  Resource<Drawable> decode(@NonNull Source source, int width, int height, @NonNull Options options)
      throws IOException {
    Drawable decoded =
        ImageDecoder.decodeDrawable(
            source, new DefaultOnHeaderDecodedListener(width, height, options));
    if (!(decoded instanceof AnimatedImageDrawable)) {
      throw new IOException(
          "Received unexpected drawable type for animated image, failing: " + decoded);
    }
    return new AnimatedImageDrawableResource((AnimatedImageDrawable) decoded);
  }

  private static final class AnimatedImageDrawableResource implements Resource<Drawable> {
    /** A totally made up number of the number of frames we think are held in memory at once... */
    private static final int ESTIMATED_NUMBER_OF_FRAMES = 2;

    private final AnimatedImageDrawable imageDrawable;

    AnimatedImageDrawableResource(AnimatedImageDrawable imageDrawable) {
      this.imageDrawable = imageDrawable;
    }

    @NonNull
    @Override
    public Class<Drawable> getResourceClass() {

View on GitHub (pinned to eb14a895d8)

Solutions

  1. Fall back to a non-animated decode path: catch the IOException and reload with .asBitmap() or via a different decoder.
  2. Use AnimatedWebpDecoder or the Glide GIF pipeline if the file is actually animated WebP and ImageDecoder misbehaves.
  3. Verify the file is genuinely animated (e.g. with a WebP inspector) and re-encode if needed.
  4. Pin to a known-good decoder via .set() options rather than relying on platform ImageDecoder.

Example fix

// before
Glide.with(ctx).load(animatedWebpUri).into(img);
// after (fall back to bitmap if animated decode fails)
Glide.with(ctx).load(animatedWebpUri)
  .error(Glide.with(ctx).asBitmap().load(animatedWebpUri))
  .into(img);
Defensive patterns

Strategy: fallback

Validate before calling

// Optional pre-check: only request animated decode when isHandled(imageType).
// In practice, rely on .error() chaining because ImageDecoder behavior is device-specific.

Try / catch

// Provide a bitmap fallback via .error() chaining instead of catching.
Glide.with(ctx).load(animatedUri)
  .error(Glide.with(ctx).asBitmap().load(animatedUri))
  .into(img);

Prevention

When it happens

Trigger: ImageDecoder produces a BitmapDrawable or other non-animated drawable for a source advertised as ANIMATED_WEBP / ANIMATED_AVIF. Happens on devices whose ImageDecoder implementation downgrades animated formats to still images.

Common situations: Loading an animated WebP/AVIF on an API 31+ device where the system ImageDecoder strips animation. A mislabeled file whose header says animated but whose payload is a single frame. OEM ImageDecoder quirks.

Related errors


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