{"record":{"id":"b0e18f783024af4b","repo":"alibaba/ARouter","slug":"interceptor-initialization-failure-must-have-a-cau","errorCode":null,"errorMessage":"Interceptor initialization failure must have a cause.","messagePattern":"Interceptor initialization failure must have a cause\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"arouter-api/src/main/java/com/alibaba/android/arouter/core/InterceptorInitState.java","lineNumber":63,"sourceCode":"    void start() {\n        synchronized (lock) {\n            status = Status.INITIALIZING;\n            failure = null;\n            lock.notifyAll();\n        }\n    }\n\n    void succeed() {\n        synchronized (lock) {\n            status = Status.SUCCEEDED;\n            failure = null;\n            lock.notifyAll();\n        }\n    }\n\n    void fail(Throwable cause) {\n        if (cause == null) {\n            throw new IllegalArgumentException(\"Interceptor initialization failure must have a cause.\");\n        }\n\n        synchronized (lock) {\n            status = Status.FAILED;\n            failure = cause;\n            lock.notifyAll();\n        }\n    }\n\n    Result await(long timeout, TimeUnit unit) throws InterruptedException {\n        if (unit == null) {\n            throw new NullPointerException(\"TimeUnit must not be null.\");\n        }\n\n        long timeoutNanos = unit.toNanos(timeout);\n        long startNanos = System.nanoTime();\n\n        synchronized (lock) {","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/alibaba/ARouter/blob/84f451d244e3fb1d0e37801de1b9ee2af2f81d68/arouter-api/src/main/java/com/alibaba/android/arouter/core/InterceptorInitState.java#L45-L81","documentation":"InterceptorInitState.fail() records a failed interceptor initialization and wakes waiters, but a null cause would leave waiters with no reason for the failure. It therefore throws IllegalArgumentException when fail() is called without a Throwable cause.","triggerScenarios":"Calling InterceptorInitState.fail(null), typically from a catch block that lost the throwable or from a caller that reports failure without an exception.","commonSituations":"Custom interceptor init wrappers that construct failure state manually; refactored catch blocks where the original exception variable was dropped.","solutions":["Always pass the caught exception to fail(), even if wrapped in a new exception","If no real exception exists, create one: fail(new IllegalStateException(\"init failed for reason X\"))","Audit init code paths that call fail() to ensure the catch variable is not discarded"],"exampleFix":"// before\ntry { interceptor.init(ctx); initState.success(); }\ncatch (Exception e) { initState.fail(null); }\n// after\ntry { interceptor.init(ctx); initState.success(); }\ncatch (Exception e) { initState.fail(e); }","handlingStrategy":"validation","validationCode":"if (cause == null) {\n    cause = new IllegalStateException(\"interceptor init failed (no cause captured)\");\n}\ninitState.fail(cause);","typeGuard":null,"tryCatchPattern":"try {\n    interceptor.init(ctx);\n} catch (Throwable t) {\n    initState.fail(t != null ? t : new IllegalStateException(\"init failed\"));\n}","preventionTips":["Never discard the catch variable when reporting init failure","Wrap non-exception failures (result flags) in a descriptive Throwable","Code-review init wrappers for null-cause paths"],"tags":["arouter","interceptor","null-argument"],"backgroundTag":"null-argument","analyzedSha":"84f451d244e3fb1d0e37801de1b9ee2af2f81d68","analyzedAt":"2026-09-06T13:30:41.084Z","contentChangedAt":"2026-09-06T13:30:41.084Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}