Tencent/matrix · error · RuntimeException
plugin stop, plugin listener is null
Error message
plugin stop, plugin listener is null
What it means
Plugin.stop() throws this when the plugin's pluginListener is null at stop time. Matrix plugins delegate lifecycle events (onStop) to a listener supplied via setPluginListener; calling stop() without one is an unrecoverable state, so the library fails fast with a RuntimeException.
Solutions
- Call plugin.setPluginListener(listener) after construction and before any lifecycle call
- Guard stop() with a null check on the listener, or use Matrix's Builder which wires listeners automatically
- Check plugin status before stopping; only stop plugins that went through start() with a listener attached
- If you own the plugin subclass, override stop() to no-op when no listener is configured
Example fix
// before Plugin plugin = new MyPlugin(); matrix.addPlugin(plugin); plugin.stop(); // after Plugin plugin = new MyPlugin(); plugin.setPluginListener(new MyPluginListener()); matrix.addPlugin(plugin); plugin.stop();
Defensive patterns
Strategy: validation
Validate before calling
if (plugin.getPluginListener() == null) {
plugin.setPluginListener(new MyPluginListener());
}
plugin.stop(); Type guard
if (plugin != null && plugin.getPluginListener() != null) { plugin.stop(); } Try / catch
try {
plugin.stop();
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("listener is null")) {
Log.w(TAG, "plugin stop skipped: no listener", e);
} else { throw e; }
} Prevention
- Always register a PluginListener immediately after constructing a plugin
- Use Matrix.Builder so listener wiring happens in one place
- Never null out plugin listeners manually
When it happens
Trigger: Calling plugin.stop() (directly or via destroy()/Matrix.onDestroy()) on a plugin that was constructed but never had setPluginListener() invoked with a non-null listener.
Common situations: Forgetting to register a listener when building a custom plugin; a listener registration call being skipped or conditional; clearing a listener reference manually before teardown; subclassing Plugin without wiring PluginListener in the Builder.
Related errors
- plugin destroy, plugin listener is null
- plugin destroy, but plugin has been already destroyed
- publish issue, but issue listener is null
- plugin start, but plugin has been already destroyed
- plugin start, but plugin has been already started
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/27b4067d9d78b296.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/plugin/Plugin.java:126
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");
}
status = PLUGIN_STOPPED;
if (pluginListener == null) {
throw new RuntimeException("plugin stop, plugin listener is null");
}
pluginListener.onStop(this);
}
@Override
public void destroy() {
// stop first
if (isPluginStarted()) {
stop();
}
if (isPluginDestroyed()) {
throw new RuntimeException("plugin destroy, but plugin has been already destroyed");
}
status = PLUGIN_DESTROYED;
if (pluginListener == null) {
throw new RuntimeException("plugin destroy, plugin listener is null");
}View on GitHub (pinned to 3b8293bd65)