{"record":{"id":"e8397069f000b44d","repo":"Tencent/matrix","slug":"plugin-start-plugin-listener-is-null","errorCode":null,"errorMessage":"plugin start, plugin listener is null","messagePattern":"plugin start, plugin listener is null","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/plugin/Plugin.java","lineNumber":108,"sourceCode":"    @Override\n    public Application getApplication() {\n        return application;\n    }\n\n    @Override\n    public void start() {\n        if (isPluginDestroyed()) {\n            throw new RuntimeException(\"plugin start, but plugin has been already destroyed\");\n        }\n\n        if (isPluginStarted()) {\n            throw new RuntimeException(\"plugin start, but plugin has been already started\");\n        }\n\n        status = PLUGIN_STARTED;\n\n        if (pluginListener == null) {\n            throw new RuntimeException(\"plugin start, plugin listener is null\");\n        }\n        pluginListener.onStart(this);\n    }\n\n    @Override\n    public void stop() {\n        if (isPluginDestroyed()) {\n            throw new RuntimeException(\"plugin stop, but plugin has been already destroyed\");\n        }\n\n        if (!isPluginStarted()) {\n            throw new RuntimeException(\"plugin stop, but plugin is never started\");\n        }\n\n        status = PLUGIN_STOPPED;\n\n        if (pluginListener == null) {\n            throw new RuntimeException(\"plugin stop, plugin listener is null\");","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/plugin/Plugin.java#L90-L126","documentation":"Plugin.start() requires the PluginListener passed to init(); it flips status to PLUGIN_STARTED before checking the listener, so a null listener throws after the status change. The listener is how the SDK notifies your code of plugin start.","triggerScenarios":"Plugin.start() when init(app, null) was called or the plugin was constructed without going through init.","commonSituations":"Manual plugin instantiation in unit tests without init; passing a null listener intentionally; deserialized or rebuilt plugin objects losing the listener reference.","solutions":["Always call plugin.init(application, pluginListener) with a non-null listener before start().","Ensure the Matrix.Builder build path (which injects the listener) is used rather than manual construction.","Pass a no-op PluginListener if no callbacks are needed."],"exampleFix":"// before\nPlugin p = new MyPlugin();\np.start();\n// after\nPlugin p = new MyPlugin();\np.init(application, new DefaultPluginListener());\np.start();","handlingStrategy":"validation","validationCode":"if (app != null && listener != null) {\n    plugin.init(app, listener);\n    plugin.start();\n}","typeGuard":null,"tryCatchPattern":"try {\n    plugin.start();\n} catch (RuntimeException e) {\n    Log.e(TAG, \"plugin listener missing at start\", e);\n}","preventionTips":["Always route plugin lifecycle through Matrix.Builder build/init","Never pass null PluginListener to init","Use a no-op listener if callbacks are unnecessary"],"tags":["android","plugins","lifecycle","null-check"],"backgroundTag":"missing-required-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"}