{"record":{"id":"14b765d9338f5a0d","repo":"bumptech/glide","slug":"you-must-call-this-method-on-the-main-thread","errorCode":null,"errorMessage":"You must call this method on the main thread","messagePattern":"You must call this method on the main thread","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/bumptech/glide/util/Util.java","lineNumber":185,"sourceCode":"\n  private static Handler getUiThreadHandler() {\n    if (mainThreadHandler == null) {\n      synchronized (Util.class) {\n        if (mainThreadHandler == null) {\n          mainThreadHandler = new Handler(Looper.getMainLooper());\n        }\n      }\n    }\n    return mainThreadHandler;\n  }\n\n  /**\n   * Throws an {@link java.lang.IllegalArgumentException} if called on a thread other than the main\n   * thread.\n   */\n  public static void assertMainThread() {\n    if (!isOnMainThread()) {\n      throw new IllegalArgumentException(\"You must call this method on the main thread\");\n    }\n  }\n\n  /** Throws an {@link java.lang.IllegalArgumentException} if called on the main thread. */\n  public static void assertBackgroundThread() {\n    if (!isOnBackgroundThread()) {\n      throw new IllegalArgumentException(\"You must call this method on a background thread\");\n    }\n  }\n\n  /** Returns {@code true} if called on the main thread, {@code false} otherwise. */\n  public static boolean isOnMainThread() {\n    return Looper.myLooper() == Looper.getMainLooper();\n  }\n\n  /** Returns {@code true} if called on a background thread, {@code false} otherwise. */\n  public static boolean isOnBackgroundThread() {\n    return !isOnMainThread();","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/bumptech/glide/blob/eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a/library/src/main/java/com/bumptech/glide/util/Util.java#L167-L203","documentation":"Thrown by Util.assertMainThread() when the calling code is not on the Android main (UI) thread. Glide's request-triggering APIs (into, clear, begin, pause, resume) must run on the main thread because they touch Views and the lifecycle, and cross-thread access would race with the UI. assertMainThread is invoked at the entry of these methods.","triggerScenarios":"Calling Glide.with(...).load(...).into(view) from a background thread, a Coroutine/Flow on Dispatchers.IO, an RxJava observeOn(Schedulers.io()) chain, an AsyncTask doInBackground, or a network callback thread.","commonSituations":"Doing network call then directly calling Glide.into in the same callback; coroutines without withContext(Dispatchers.Main); RxJava missing observeOn(AndroidSchedulers.mainThread()); threading bugs in custom decoders.","solutions":["Hop to the main thread before calling into(): withContext(Dispatchers.Main) { Glide.with(...).into(iv) }","In RxJava, observeOn(AndroidSchedulers.mainThread()) before the subscribe that calls Glide","Use view.post { Glide.with(view)... } from a background thread","Keep all request-triggering Glide calls (into/clear/begin/pause/resume) on the UI thread"],"exampleFix":"// before\nlaunch(Dispatchers.IO) {\n  val url = api.fetchImageUrl()\n  Glide.with(ctx).load(url).into(imageView) // throws: not main thread\n}\n\n// after\nlaunch(Dispatchers.IO) {\n  val url = api.fetchImageUrl()\n  withContext(Dispatchers.Main) {\n    Glide.with(ctx).load(url).into(imageView)\n  }\n}","handlingStrategy":"validation","validationCode":"fun isMainThread(): Boolean = Looper.myLooper() == Looper.getMainLooper()\n\nif (isMainThread()) {\n  Glide.with(ctx).load(url).into(imageView)\n} else {\n  // hop to main thread first\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always run into()/clear()/begin()/pause()/resume() on the main thread","In coroutines use withContext(Dispatchers.Main); in RxJava observeOn(AndroidSchedulers.mainThread())","From a background callback use view.post { Glide.with(view)... }","Lint for Glide calls inside IO-thread scopes"],"tags":["android","glide","threading","main-thread","concurrency"],"backgroundTag":null,"analyzedSha":"eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a","analyzedAt":"2026-08-14T01:43:54.821Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}