{"record":{"id":"2581ee7350b6c316","repo":"bumptech/glide","slug":"received-unexpected-drawable-type-for-animated-ima","errorCode":null,"errorMessage":"Received unexpected drawable type for animated image, failing: {decoded}","messagePattern":"Received unexpected drawable type for animated image, failing: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/bumptech/glide/load/resource/drawable/AnimatedImageDecoder.java","lineNumber":76,"sourceCode":"  @Synthetic\n  boolean handles(InputStream is) throws IOException {\n    return isHandled(ImageHeaderParserUtils.getType(imageHeaderParsers, is, arrayPool));\n  }\n\n  @SuppressWarnings(\"checkstyle:UnnecessaryParentheses\") // Readability\n  private boolean isHandled(ImageType imageType) {\n    return imageType == ImageType.ANIMATED_WEBP\n        || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && imageType == ImageType.ANIMATED_AVIF);\n  }\n\n  @Synthetic\n  Resource<Drawable> decode(@NonNull Source source, int width, int height, @NonNull Options options)\n      throws IOException {\n    Drawable decoded =\n        ImageDecoder.decodeDrawable(\n            source, new DefaultOnHeaderDecodedListener(width, height, options));\n    if (!(decoded instanceof AnimatedImageDrawable)) {\n      throw new IOException(\n          \"Received unexpected drawable type for animated image, failing: \" + decoded);\n    }\n    return new AnimatedImageDrawableResource((AnimatedImageDrawable) decoded);\n  }\n\n  private static final class AnimatedImageDrawableResource implements Resource<Drawable> {\n    /** A totally made up number of the number of frames we think are held in memory at once... */\n    private static final int ESTIMATED_NUMBER_OF_FRAMES = 2;\n\n    private final AnimatedImageDrawable imageDrawable;\n\n    AnimatedImageDrawableResource(AnimatedImageDrawable imageDrawable) {\n      this.imageDrawable = imageDrawable;\n    }\n\n    @NonNull\n    @Override\n    public Class<Drawable> getResourceClass() {","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/bumptech/glide/blob/eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a/library/src/main/java/com/bumptech/glide/load/resource/drawable/AnimatedImageDecoder.java#L58-L94","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fall back to a non-animated decode path: catch the IOException and reload with .asBitmap() or via a different decoder.","Use AnimatedWebpDecoder or the Glide GIF pipeline if the file is actually animated WebP and ImageDecoder misbehaves.","Verify the file is genuinely animated (e.g. with a WebP inspector) and re-encode if needed.","Pin to a known-good decoder via .set() options rather than relying on platform ImageDecoder."],"exampleFix":"// before\nGlide.with(ctx).load(animatedWebpUri).into(img);\n// after (fall back to bitmap if animated decode fails)\nGlide.with(ctx).load(animatedWebpUri)\n  .error(Glide.with(ctx).asBitmap().load(animatedWebpUri))\n  .into(img);","handlingStrategy":"fallback","validationCode":"// Optional pre-check: only request animated decode when isHandled(imageType).\n// In practice, rely on .error() chaining because ImageDecoder behavior is device-specific.","typeGuard":null,"tryCatchPattern":"// Provide a bitmap fallback via .error() chaining instead of catching.\nGlide.with(ctx).load(animatedUri)\n  .error(Glide.with(ctx).asBitmap().load(animatedUri))\n  .into(img);","preventionTips":["Chain a bitmap .error() request for animated sources.","Test animated WebP/AVIF on multiple API levels.","Prefer ANIMATED_AVIF only on API 31+ where supported."],"tags":["animated","webp","avif","imagedecoder","android"],"backgroundTag":null,"analyzedSha":"eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a","analyzedAt":"2026-08-14T01:43:54.821Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}