{"record":{"id":"f4a396434f523c28","repo":"Tencent/matrix","slug":"plugin-start-but-plugin-has-been-already-started","errorCode":null,"errorMessage":"plugin start, but plugin has been already started","messagePattern":"plugin start, but plugin has been already started","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":102,"sourceCode":"        }\n\n        //MatrixLog.e(TAG, \"detect issue:%s\", issue);\n        pluginListener.onReportIssue(issue);\n    }\n\n    @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\");","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/plugin/Plugin.java#L84-L120","documentation":"Thrown from Plugin.start() when the plugin is already in PLUGIN_STARTED state. start() is intended to be called exactly once per plugin lifecycle; a second call means the caller (usually Matrix.onCreate) is double-starting the plugin, so the guard throws rather than re-invoking onStart and re-registering the plugin with its listener.","triggerScenarios":"Calling plugin.start() (or Matrix.with().startAllPlugins()) twice without an intervening stop().","commonSituations":"Calling startAllPlugins() in both Application.onCreate and onForeground; re-entry from lifecycle callbacks; duplicated bootstrap code paths.","solutions":["Guard start with plugin.isPluginStarted() before calling.","Track whether startAllPlugins() has run (e.g. a boolean in your Application).","Call stop() before start() if a restart is intended."],"exampleFix":"// before\nif (!plugin.isPluginStarted()) {\n    plugin.start();\n}\nplugin.start();\n// after\nif (!plugin.isPluginStarted()) {\n    plugin.start();\n}","handlingStrategy":"type-guard","validationCode":"if (!plugin.isPluginStarted() && !plugin.isPluginDestroyed()) {\n    plugin.start();\n}","typeGuard":"boolean canStart(Plugin p) { return !p.isPluginStarted() && !p.isPluginDestroyed(); }","tryCatchPattern":"try {\n    plugin.start();\n} catch (RuntimeException e) {\n    Log.w(TAG, \"plugin already started\", e);\n}","preventionTips":["Guard startAllPlugins() with a once-per-process flag","Do not call start from both onCreate and onForeground unconditionally","Check isPluginStarted() before every start()"],"tags":["android","plugins","lifecycle","double-start"],"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"}