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

  1. Call plugin.setPluginListener(listener) after construction and before any lifecycle call
  2. Guard stop() with a null check on the listener, or use Matrix's Builder which wires listeners automatically
  3. Check plugin status before stopping; only stop plugins that went through start() with a listener attached
  4. 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

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


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)