{"record":{"id":"13eae118981b52ca","repo":"bumptech/glide","slug":"cannot-restart-a-running-request","errorCode":null,"errorMessage":"Cannot restart a running request","messagePattern":"Cannot restart a running request","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/bumptech/glide/request/SingleRequest.java","lineNumber":235,"sourceCode":"  public void begin() {\n    synchronized (requestLock) {\n      assertNotCallingCallbacks();\n      stateVerifier.throwIfRecycled();\n      startTime = LogTime.getLogTime();\n      if (model == null) {\n        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {\n          width = overrideWidth;\n          height = overrideHeight;\n        }\n        // Only log at more verbose log levels if the user has set a fallback drawable, because\n        // fallback Drawables indicate the user expects null models occasionally.\n        int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;\n        onLoadFailed(new GlideException(\"Received null model\"), logLevel);\n        return;\n      }\n\n      if (status == Status.RUNNING) {\n        throw new IllegalArgumentException(\"Cannot restart a running request\");\n      }\n\n      // If we're restarted after we're complete (usually via something like a notifyDataSetChanged\n      // that starts an identical request into the same Target or View), we can simply use the\n      // resource and size we retrieved the last time around and skip obtaining a new size, starting\n      // a new load etc. This does mean that users who want to restart a load because they expect\n      // that the view size has changed will need to explicitly clear the View or Target before\n      // starting the new load.\n      if (status == Status.COMPLETE) {\n        onResourceReady(\n            resource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);\n        return;\n      }\n\n      // Restarts for requests that are neither complete nor running can be treated as new requests\n      // and can run again from the beginning.\n\n      experimentalNotifyRequestStarted(model);","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/bumptech/glide/blob/eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a/library/src/main/java/com/bumptech/glide/request/SingleRequest.java#L217-L253","documentation":"Thrown by SingleRequest.begin() when begin() is invoked while the request status is already RUNNING. A SingleRequest represents one in-flight load and cannot be restarted from the running state; it must be cleared first. Calling begin() again on a complete request is allowed (it short-circuits to the cached resource), but a running one is a programming error.","triggerScenarios":"Calling request.begin() manually twice; calling into() twice on the same Target without a clear() between them while the first load is still active; calling Glide.with(...).load(...).into(sameView) rapidly (e.g. in a scrolling binder) before the first load resolves.","commonSituations":"RecyclerView adapters that rebind the same ViewHolder and re-trigger Glide.into() without first calling Glide.with(view).clear(target); Pagination/refresh logic that restarts a request on the same Target; custom Targets that call request.begin() in a callback.","solutions":["Call Glide.with(view).clear(target) (or RequestManager.clear(target)) before starting a new load into the same Target/View","Let Glide manage the request lifecycle via into(ImageView) which clears the previous request automatically — avoid managing SingleRequest instances yourself","If holding a Request reference, check request.isRunning() before begin() and clear() if needed","In RecyclerView, use a stable request per ViewHolder and clear in onViewRecycled"],"exampleFix":"// before\nfun bind(url: String) {\n  Glide.with(itemView).load(url).into(imageView) // rebind triggers second begin() while first still RUNNING\n}\n\n// after\nprivate val target by lazy { Glide.with(itemView).asDrawable().load(placeholder).into(imageView) }\nfun bind(url: String) {\n  Glide.with(itemView).clear(imageView) // clear previous request first\n  Glide.with(itemView).load(url).into(imageView)\n}","handlingStrategy":"validation","validationCode":"// Prefer letting Glide own the request via into(ImageView); it clears the previous one.\n// If you hold a Request reference:\nif (request.isRunning) {\n  glide.with(view).clear(target)\n}\nrequest.begin()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always clear a Target/View (Glide.with(view).clear(...)) before starting a new load into it","Avoid holding and reusing SingleRequest instances; use the high-level into(ImageView) API","In RecyclerView, clear in onViewRecycled and rebind cleanly"],"tags":["android","glide","lifecycle","request","recyclerview"],"backgroundTag":null,"analyzedSha":"eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a","analyzedAt":"2026-08-14T01:43:54.821Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}