Tencent/matrix · error · RuntimeException
plugin start, but plugin has been already started
Error message
plugin start, but plugin has been already started
What it means
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.
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.
Example fix
// before
if (!plugin.isPluginStarted()) {
plugin.start();
}
plugin.start();
// after
if (!plugin.isPluginStarted()) {
plugin.start();
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!plugin.isPluginStarted() && !plugin.isPluginDestroyed()) {
plugin.start();
} Type guard
boolean canStart(Plugin p) { return !p.isPluginStarted() && !p.isPluginDestroyed(); } Try / catch
try {
plugin.start();
} catch (RuntimeException e) {
Log.w(TAG, "plugin already started", e);
} Prevention
- Guard startAllPlugins() with a once-per-process flag
- Do not call start from both onCreate and onForeground unconditionally
- Check isPluginStarted() before every start()
When it happens
Trigger: Calling plugin.start() (or Matrix.with().startAllPlugins()) twice without an intervening stop().
Common situations: Calling startAllPlugins() in both Application.onCreate and onForeground; re-entry from lifecycle callbacks; duplicated bootstrap code paths.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- plugin start, but plugin has been already destroyed
- plugin start, plugin listener is null
- plugin stop, but plugin has been already destroyed
- plugin stop, but plugin is never started
- plugin with tag is already exist
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/f4a396434f523c28.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/plugin/Plugin.java:102
}
//MatrixLog.e(TAG, "detect issue:%s", issue);
pluginListener.onReportIssue(issue);
}
@Override
public Application getApplication() {
return application;
}
@Override
public void start() {
if (isPluginDestroyed()) {
throw new RuntimeException("plugin start, but plugin has been already destroyed");
}
if (isPluginStarted()) {
throw new RuntimeException("plugin start, but plugin has been already started");
}
status = PLUGIN_STARTED;
if (pluginListener == null) {
throw new RuntimeException("plugin start, plugin listener is null");
}
pluginListener.onStart(this);
}
@Override
public void stop() {
if (isPluginDestroyed()) {
throw new RuntimeException("plugin stop, but plugin has been already destroyed");
}
if (!isPluginStarted()) {
throw new RuntimeException("plugin stop, but plugin is never started");View on GitHub (pinned to 3b8293bd65)