{"record":{"id":"bc578cdbd1d5fdd4","repo":"Tencent/matrix","slug":"should-not-call-this-from-main-thread","errorCode":null,"errorMessage":"Should not call this from main thread!","messagePattern":"Should not call this from main thread!","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-backtrace/src/main/java/com/tencent/matrix/backtrace/WarmUpService.java","lineNumber":100,"sourceCode":"                mReq = null;\n                synchronized (mBound) {\n                    mBound[0] = false;\n                    mBound.notifyAll();\n                }\n                MatrixLog.i(TAG, \"This remote invoker(%s) disconnected.\", this);\n\n                synchronized (mResult) {\n                    mResult[0] = null;\n                    mResult.notifyAll();\n                }\n            }\n        };\n\n        private final boolean[] mBound = {false};\n\n        private void checkThread() {\n            if (Looper.getMainLooper() == Looper.myLooper()) {\n                throw new RuntimeException(\"Should not call this from main thread!\");\n            }\n        }\n\n        @Override\n        public boolean isConnected() {\n            return mBound[0];\n        }\n\n        @Override\n        public boolean connect(Context context, Bundle args) {\n\n            checkThread();\n\n            if (mBound[0]) {\n                return true;\n            }\n\n            MatrixLog.i(TAG, \"Start connecting to remote. (%s)\", this.hashCode());","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-backtrace/src/main/java/com/tencent/matrix/backtrace/WarmUpService.java#L82-L118","documentation":"WarmUpService.checkThread() throws a RuntimeException if the current thread is the Android main (UI) thread. Backtrace warm-up work (binding, library loading) must never run on the main thread because it performs blocking I/O that would jank or ANR the UI. The guard exists to fail fast when callers misuse the service from the wrong thread.","triggerScenarios":"Calling any WarmUpService API that invokes checkThread() (e.g. via connect()) while Looper.getMainLooper() == Looper.myLooper(), i.e. calling it from an Activity onCreate/onResume, a main-thread Handler, or the Application.onCreate main path without spawning a worker thread.","commonSituations":"Developers initializing Matrix backtrace warm-up directly inside Activity.onCreate or Application.onCreate without a background thread; calling connect() from a main-thread callback or runOnUiThread block.","solutions":["Move the connect()/warm-up call onto a background thread, e.g. new Thread(() -> warmUpService.connect(...)).start() or a coroutine on Dispatchers.IO.","Post the call to a worker Handler: new Handler(HandlerThread looper).post(this::connect).","If called in Application.onCreate, defer warm-up with an executor or WorkManager instead of the main thread."],"exampleFix":"// before\n@Override\nprotected void onCreate(Bundle s) {\n    super.onCreate(s);\n    warmUpService.connect(); // throws on main thread\n}\n\n// after\n@Override\nprotected void onCreate(Bundle s) {\n    super.onCreate(s);\n    Executors.newSingleThreadExecutor().execute(warmUpService::connect);\n}","handlingStrategy":"validation","validationCode":"if (Looper.getMainLooper() == Looper.myLooper()) {\n    // move to worker thread before calling connect()\n    workerHandler.post(() -> warmUpService.connect());\n} else {\n    warmUpService.connect();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always invoke warm-up/backtrace APIs from a dedicated HandlerThread or executor.","Never call blocking SDK methods directly inside Activity/Application lifecycle callbacks on the main thread.","Centralize warm-up calls in a background-init helper used app-wide."],"tags":["android","threading","main-thread","backtrace"],"backgroundTag":"invalid-state-transition","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}