{"record":{"id":"2b8958c1d62e18aa","repo":"Tencent/matrix","slug":"publish-issue-but-issue-listener-is-null","errorCode":null,"errorMessage":"publish issue, but issue listener is null","messagePattern":"publish issue, but issue listener is null","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/report/IssuePublisher.java","lineNumber":45,"sourceCode":" */\n\npublic class IssuePublisher {\n\n    private final OnIssueDetectListener    mIssueListener;\n    private final HashSet<String> mPublishedMap;\n\n    public interface OnIssueDetectListener {\n        void onDetectIssue(Issue issue);\n    }\n\n    public IssuePublisher(OnIssueDetectListener issueDetectListener) {\n        mPublishedMap = new HashSet<>();\n        this.mIssueListener = issueDetectListener;\n    }\n\n    protected void publishIssue(Issue issue) {\n        if (mIssueListener == null) {\n            throw new RuntimeException(\"publish issue, but issue listener is null\");\n        }\n        if (issue != null) {\n            mIssueListener.onDetectIssue(issue);\n        }\n    }\n\n    protected boolean isPublished(String key) {\n        if (key == null) {\n            return false;\n        }\n\n        return mPublishedMap.contains(key);\n    }\n\n    protected void markPublished(String key) {\n        if (key == null) {\n            return;\n        }","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/report/IssuePublisher.java#L27-L63","documentation":"IssuePublisher.publishIssue() throws when mIssueListener is null. Subclasses (e.g. individual detectors) call publishIssue to hand detected issues to a registered IssueListener; without a listener there is nowhere to deliver the issue, so Matrix fails fast.","triggerScenarios":"A detector subclass calls publishIssue(issue) before its listener was registered, or the listener was never set on the IssuePublisher subclass at all.","commonSituations":"Custom detectors extending IssuePublisher without calling setIssueListener; configuring a detector (e.g. SQLiteLint, IOCanary) without its reporter callback; publishing issues before plugin init completes.","solutions":["Call setIssueListener() on the publisher before any detection runs","Ensure the plugin's PluginListener.onStart wires the issue listener before detectors start working","Guard publishIssue call sites with a null listener check","Verify plugin initialization order so the listener is attached before detection begins"],"exampleFix":"// before\npublic class MyDetector extends IssuePublisher {\n    void onFound(Issue issue) { publishIssue(issue); }\n}\n\n// after\npublic class MyDetector extends IssuePublisher {\n    MyDetector() { setIssueListener(listener); }\n    void onFound(Issue issue) { publishIssue(issue); }\n}","handlingStrategy":"validation","validationCode":"if (getIssueListener() == null) {\n    setIssueListener(defaultListener);\n}\npublishIssue(issue);","typeGuard":"if (this.mIssueListener != null) { publishIssue(issue); }","tryCatchPattern":"try {\n    publishIssue(issue);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"issue listener is null\")) {\n        Log.w(TAG, \"issue dropped: no listener registered\");\n    } else { throw e; }\n}","preventionTips":["Register the IssueListener in the detector's constructor or onStart","Never start detection before the listener is attached","Provide a default no-op listener in custom IssuePublisher subclasses"],"tags":["android","null-listener","issue-reporting","plugin"],"backgroundTag":"null-argument","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"}