bumptech/glide · error · IllegalStateException
You can't start or clear loads in RequestListener or Target
Error message
You can't start or clear loads in RequestListener or Target callbacks. If you're trying to start a fallback request when a load fails, use RequestBuilder#error(RequestBuilder). Otherwise consider posting your into() or clear() calls to the main thread using a Handler instead.
What it means
Thrown by SingleRequest.assertNotCallingCallbacks() (invoked at the start of begin/clear) when isCallingCallbacks is true — i.e. you are synchronously inside a RequestListener.onResourceReady/onLoadFailed or a Target callback (onResourceReady, onLoadFailed, onLoadCleared) and you attempt to start a new Glide load or clear one from within that callback. Glide holds the requestLock during callbacks and re-entrant start/clear would deadlock or corrupt state, hence the explicit guard (issue #2413).
Source
Thrown at library/src/main/java/com/bumptech/glide/request/SingleRequest.java:307
*
* @see #clear()
*/
@GuardedBy("requestLock")
private void cancel() {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
target.removeCallback(this);
if (loadStatus != null) {
loadStatus.cancel();
loadStatus = null;
}
}
// Avoids difficult to understand errors like #2413.
@GuardedBy("requestLock")
private void assertNotCallingCallbacks() {
if (isCallingCallbacks) {
throw new IllegalStateException(
"You can't start or clear loads in RequestListener or"
+ " Target callbacks. If you're trying to start a fallback request when a load fails,"
+ " use RequestBuilder#error(RequestBuilder). Otherwise consider posting your into()"
+ " or clear() calls to the main thread using a Handler instead.");
}
}
/**
* Cancels the current load if it is in progress, clears any resources held onto by the request
* and replaces the loaded resource if the load completed with the placeholder.
*
* <p>Cleared requests can be restarted with a subsequent call to {@link #begin()}
*
* @see #cancel()
*/
@Override
public void clear() {
Resource<R> toRelease = null;View on GitHub (pinned to eb14a895d8)
Solutions
- For fallback-on-failure use the built-in API: .load(primary).error(Glide.with(ctx).load(fallback))
- If you must start a new load from a callback, post it to the main thread Handler (or use view.post { }) so it runs after the callback returns
- Use RequestBuilder.thumbnail() or .error(RequestBuilder) for chained loads instead of doing them in listeners
- Never call RequestManager.clear(target) for the same target from inside that target's own callback
Example fix
// before
listener = object : RequestListener<Drawable> {
override fun onLoadFailed(...): Boolean {
Glide.with(view).load(fallbackUrl).into(target) // IllegalStateException
return true
}
}
// after - use the error(RequestBuilder) API
Glide.with(view)
.load(primaryUrl)
.error(Glide.with(view).load(fallbackUrl))
.into(target) Defensive patterns
Strategy: fallback
Validate before calling
// Structural rule: do NOT start/clear loads inside RequestListener/Target callbacks. // Use RequestBuilder.error(RequestBuilder) for fallback loads instead.
Prevention
- Use .error(Glide.with(ctx).load(fallback)) for fallback-on-failure instead of listener-driven loads
- If a callback must trigger a load, post it: view.post { Glide.with(view)... }
- Never call RequestManager.clear(target) for the same target inside that target's own callback
When it happens
Trigger: Inside RequestListener.onResourceReady starting Glide.with(...).load(fallbackUrl).into(target); inside Target.onLoadFailed calling clear() on the same request; chaining a thumbnail->error request manually inside the listener rather than using RequestBuilder.error(RequestBuilder).
Common situations: Implementing a fallback-image pattern manually in onLoadFailed; preloading the next image inside onResourceReady; calling notifyDataSetChanged() that synchronously triggers a Glide.into() from within a callback.
Related errors
- You cannot start a load on a fragment before it is attached
- Cannot restart a running request
- You must call this method on the main thread
- You must call this method on a background thread
- Already released
AI-assisted analysis of bumptech/glide@eb14a895d8 (2026-08-14).
Data as JSON: /api/errors/b73f180ff6600885.
Report an issue: GitHub.