koral--/android-gif-drawable · error · IllegalArgumentException
Position is not positive
Error message
Position is not positive
What it means
GifDrawable.seekTo validates the position in milliseconds is non-negative before scheduling an async seek on its executor. Negative positions are meaningless in a GIF timeline, so it throws IllegalArgumentException immediately on the calling thread.
Solutions
- Clamp before calling: Math.max(0, position)
- Guard the source: treat sentinel/negative values as 'restart from 0' by calling seekTo(0) or resetAnimation()
- Catch IllegalArgumentException around seekTo and fall back to seekTo(0)
Example fix
// before gifDrawable.seekTo(positionMs); // after gifDrawable.seekTo(Math.max(0, positionMs));
Defensive patterns
Strategy: validation
Validate before calling
if (positionMs < 0) { positionMs = 0; } Type guard
int clampPosition(int pos) { return Math.max(0, pos); } Try / catch
try { gifDrawable.seekTo(pos); } catch (IllegalArgumentException e) { gifDrawable.seekTo(0); } Prevention
- Clamp all computed seek positions with Math.max(0, ...)
- Treat persisted -1 position sentinels as 0 on restore
- Keep seek-target arithmetic in one utility that guarantees non-negativity
When it happens
Trigger: Calling seekTo() with a negative value, e.g. computing position from currentTime - offset, or from an external player state that went negative.
Common situations: Custom media controls computing seek targets by subtraction; binding progress values that can be negative; restoring saved state with a sentinel -1 meaning 'unknown position'.
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
- Sample size out of range <1, 65535>
- Frame index is not positive
- Bitmap is recycled
- Bitmap ia too small, size must be greater than or equal to…
- Only Config.ARGB_8888 is supported. Current bitmap config
AI-assisted analysis of koral--/android-gif-drawable@26ff795f78 (2026-09-10).
Data as JSON: /api/errors/7370cd4ac8defa0c.
Report an issue: GitHub.
Appendix: source
Thrown at android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawable.java:537
return mNativeInfoHandle.getCurrentPosition();
}
/**
* Seeks animation to given absolute position (within given loop) and refreshes the canvas.<br>
* If <code>position</code> is greater than duration of the loop of animation (or whole animation if there is no loop)
* then animation will be sought to the end, no exception will be thrown.<br>
* NOTE: all frames from current (or first one if seeking backward) to desired one must be rendered sequentially to perform seeking.
* It may take a lot of time if number of such frames is large.
* Method is thread-safe. Decoding is performed in background thread and drawable is invalidated automatically
* afterwards.
*
* @param position position to seek to in milliseconds
* @throws IllegalArgumentException if <code>position</code><0
*/
@Override
public void seekTo(@IntRange(from = 0, to = Integer.MAX_VALUE) final int position) {
if (position < 0) {
throw new IllegalArgumentException("Position is not positive");
}
mExecutor.execute(new SafeRunnable(this) {
@Override
public void doWork() {
mNativeInfoHandle.seekToTime(position, mBuffer);
mGifDrawable.mInvalidationHandler.sendEmptyMessageAtTime(MSG_TYPE_INVALIDATION, 0);
}
});
}
/**
* Like {@link #seekTo(int)} but performs operation synchronously on current thread
*
* @param position position to seek to in milliseconds
* @throws IllegalArgumentException if <code>position</code><0
*/
public void seekToBlocking(@IntRange(from = 0, to = Integer.MAX_VALUE) final int position) {
if (position < 0) {View on GitHub (pinned to 26ff795f78)