koral--/android-gif-drawable · error · IllegalArgumentException

Bitmap is recycled

Error message

Bitmap is recycled

What it means

checkBuffer validates the Bitmap passed to seekToTime/seekToFrame before native code renders into it. If the bitmap has been recycled, drawing into it would crash the native layer, so the library throws IllegalArgumentException early with a clear message.

Solutions

  1. Do not recycle the bitmap while the decoder may still use it; keep a strong reference until done seeking
  2. Check bitmap.isRecycled() before calling seekTo* and allocate a fresh ARGB_8888 bitmap if recycled
  3. Wrap seek calls in try-catch for IllegalArgumentException and recreate the buffer

Example fix

// before
decoder.seekToFrame(frameIndex, bitmap); // bitmap may be recycled
// after
if (bitmap == null || bitmap.isRecycled()) {
    bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
decoder.seekToFrame(frameIndex, bitmap);
Defensive patterns

Strategy: validation

Validate before calling

if (buffer == null || buffer.isRecycled()) { buffer = Bitmap.createBitmap(decoder.getWidth(), decoder.getHeight(), Bitmap.Config.ARGB_8888); }

Type guard

Bitmap ensureLiveBitmap(Bitmap b, int w, int h) { return (b == null || b.isRecycled() || b.getWidth() < w || b.getHeight() < h) ? Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888) : b; }

Try / catch

try { decoder.seekToFrame(i, buffer); } catch (IllegalArgumentException e) { buffer = Bitmap.createBitmap(decoder.getWidth(), decoder.getHeight(), Bitmap.Config.ARGB_8888); decoder.seekToFrame(i, buffer); }

Prevention

When it happens

Trigger: Calling seekToTime(millis, bitmap) or seekToFrame(index, bitmap) on GifDecoder with a Bitmap on which recycle() was already called (e.g. after releasing previous resources, or bitmap evicted and recycled by your own cache).

Common situations: Reusing a bitmap field after an activity/fragment teardown recycled it; bitmap pools recycling on background threads while a seek is in flight; confusing GifDrawable's internal buffer with a user-supplied bitmap that was recycled elsewhere.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of koral--/android-gif-drawable@26ff795f78 (2026-09-10). Data as JSON: /api/errors/7a0841ce963cfef1. Report an issue: GitHub.

Appendix: source

Thrown at android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDecoder.java:162

	}

	/**
	 * @return true if GIF is animated (has at least 2 frames and positive duration), false otherwise
	 */
	public boolean isAnimated() {
		return mGifInfoHandle.getNumberOfFrames() > 1 && getDuration() > 0;
	}

	/**
	 * See {@link GifDrawable#recycle()}
	 */
	public void recycle() {
		mGifInfoHandle.recycle();
	}

	private void checkBuffer(final Bitmap buffer) {
		if (buffer.isRecycled()) {
			throw new IllegalArgumentException("Bitmap is recycled");
		}
		if (buffer.getWidth() < mGifInfoHandle.getWidth() || buffer.getHeight() < mGifInfoHandle.getHeight()) {
			throw new IllegalArgumentException("Bitmap ia too small, size must be greater than or equal to GIF size");
		}
		if (buffer.getConfig() != Bitmap.Config.ARGB_8888) {
			throw new IllegalArgumentException("Only Config.ARGB_8888 is supported. Current bitmap config: " + buffer.getConfig());
		}
	}
}

View on GitHub (pinned to 26ff795f78)