Skip to content

bug: frontend: Safe Mode and --only-bundled-plugins always show the "Plugin Errors" dialog, and removing a Missing plugin in the Plugin Manager changes the wrong plugin (upstream #13948, #14005)Β #1079

Closed

Description

@rdoupe

Two upstream OBS bugs in the Plugin Manager, both reported by FiniteSingularity: obsproject/obs-studio#13948 (Safe Mode lists third-party plugins as Missing) and obsproject/obs-studio#14005 (the trash button for a Missing plugin doesn't always remove it). Warchamp7 fixed them upstream in obsproject/obs-studio#14001 and obsproject/obs-studio#14008, both merged on 2026-10-08. Neither fix is in obs-rust yet. One issue for both because #14008 builds on #14001 and they touch the same three files.

Location

  1. frontend/plugin-manager/PluginManager.cpp loadAllPlugins() (line 96) only sets loadState_ inside if (loadMode_ == Mode::Full). Safe Mode and --only-bundled-plugins load with Mode::CoreOnly (frontend/OBSApp.cpp line 1963), so loadState_ keeps its default State::Failure (PluginManager.hpp line 53). OBSApp::handlePluginLoadState() (OBSApp.cpp line 1969) then opens the modal "Plugin Errors" box (handlePluginFailure(), exec()) after the main window loads, on every such start.
  2. frontend/plugin-manager/PluginManagerWindow.cpp setupInstalledPage() (line 135): a cached plugin that is not loaded is Status::Missing. In both modes that is every third-party plugin. Each such row gets a trash button that deletes the plugin's saved entry (enabled state and the types it provides).
  3. Same file, line 164: each row's Entry keeps &metadata, a pointer into the window's modules_ vector. The trash handler (line 207) looks its entry up by address and calls modules_.erase(), which shifts every later element down one slot. After that, each later row points at the next plugin: its trash button removes the wrong entry, and its toggle (InstalledPluginRow.cpp line 135, metadata->enabled = checked) turns a different plugin on or off. PluginManager::open() saves the result to plugin_manager/modules.json when the window is saved.

Class

Logic error (a state that is never set) and use of invalidated pointers. The modal dialog blocks unattended starts, and the Plugin Manager can delete or disable the wrong plugin's settings. No crash was seen.

How it is reached

  • --safe-mode, Help > Restart in Safe Mode, the crash dialog's "Launch in Safe Mode", or --only-bundled-plugins: the "Plugin Errors" dialog ("OBS Studio was not able to load all third-party plugins") appears although nothing failed. Tools > Plugin Manager then lists every third-party plugin as Missing, with a trash button.
  • Normal start with two or more Missing entries (plugins that were uninstalled): remove one, then use the trash button or toggle of any row after it.

Reproduced in 0.1.0-beta.20261014

The released AppImage (built from 9e2325e), headless (private Xvfb and D-Bus), one profile across the starts, a small test plugin (it loads and does nothing) in the user plugin folder. The dialog was detected by its window title.

Start "Plugin Errors" dialog Plugin Manager SIGTERM while it is up
normal (control, twice) none - quits in 0.2 s
--only-bundled-plugins shown the test plugin and every other third-party plugin under "Missing", each with a trash button OBS still running after 20 s
--safe-mode shown same, under the "All plugins temporarily disabled by Safe Mode" label -

For #14005, plugin_manager/modules.json listed three plugins that do not exist (ghost-a, ghost-b, ghost-c, so they show as Missing) before two that load (the test plugin and a second test plugin that drives the window). In the Plugin Manager, a test plugin clicked the way a user does: the trash button of ghost-a, the toggle of the first test plugin (off), the trash button of ghost-c, then Save.

Expected 0.1.0-beta.20261014
ghost-a removed removed
ghost-c removed kept
first test plugin kept, turned off removed
second test plugin kept, on turned off
restart prompt (a plugin was turned off) shown not shown

Proposed fix and failing test

Port both upstream PRs, crediting Warchamp7 as the author of his commits:

  • #14001: loadAllPlugins() reports Success when the mode is not Full. In Safe Mode the Plugin Manager lists the cached plugins as Installed with a "Disabled" chip (no trash button) and shows a notice.
  • The same for --only-bundled-plugins (not in #14001), with a notice that names the flag.
  • #14008: each row keeps a copy of its ModuleInfo, and the trash button and toggle find their plugin in modules_ by module name. Upstream, isEnabledPluginsChanged() still reads the rows' copies, which never change, so turning a plugin off no longer shows the restart notice or asks to restart. Read modules_ there instead.

RED test: test_plugin_manager (new, cmocka + Qt Widgets on the offscreen platform, no display). It builds the real PluginManager, PluginManagerWindow and InstalledPluginRow against stand-ins for the frontend app and the libobs module calls. 5 of 8 cases fail today:

  • a core-only load reports Success;
  • Safe Mode lists cached plugins as installed and disabled, with no trash button;
  • --only-bundled-plugins does the same;
  • removing ghost-a and then ghost-c keeps ghost-b and both loaded plugins;
  • after removing ghost-a, turning plugin-x off turns plugin-x off (not plugin-y).

Guards that pass today: a full load still reports a plugin failure; on a normal start a plugin that is gone is still Missing and can be removed; turning a plugin off asks for a restart.

Activity

  1. rdoupe commented on Oct 16, 2026

    @rdoupe
    CollaboratorAuthor

    Claiming: this issue.

    A port of Warchamp7's two upstream fixes (obsproject/obs-studio#14001 and #14008), with his commits credited to him:

    1. RED: test_plugin_manager builds the real Plugin Manager sources on Qt's offscreen platform. A core-only load (Safe Mode, --only-bundled-plugins) must report success. In both modes the cached plugins must be listed as installed and disabled, without a trash button. Removing Missing entries must remove the clicked ones, and a toggle after a removal must change its own plugin. Guards cover a full load that reports failures, a real Missing plugin on a normal start, and the restart prompt after a toggle. 5 of 8 fail today.
    2. GREEN: the two upstream PRs, the same handling for --only-bundled-plugins, and one change to #14008 so that turning a plugin off still asks for a restart.
    3. RED and GREEN in both lanes, full ctest in both lanes, then the release cases again on the fixed build: no dialog in Safe Mode or with --only-bundled-plugins, and the right rows after removals.
  2. added
    claimedAn agent or person has claimed this; check the claim comment before starting
    on Oct 16, 2026
  3. rdoupe commented on Oct 16, 2026

    @rdoupe
    CollaboratorAuthor

    @FiniteSingularity you reported both of these upstream: obsproject/obs-studio#13948 (Safe Mode lists third-party plugins as Missing) and obsproject/obs-studio#14005 (the trash button doesn't always remove a Missing plugin). Heads-up that both are fixed here in obs-rust too. #1080 merged today with a regression test. It ports Warchamp7's upstream fixes (obsproject/obs-studio#14001 and #14008).

    What changed:

    • Safe Mode and --only-bundled-plugins no longer show the "Plugin Errors" dialog. A core-only load never set the load state, so it stayed at its default of "failure". The Plugin Manager now lists the skipped plugins as installed and disabled, under a notice, without the trash button that would delete their saved settings. Upstream handles Safe Mode; here --only-bundled-plugins gets the same treatment.
    • Removing a Missing plugin removes that plugin. Each row held a pointer into the module list, and removing an entry shifted everything after it, so the later trash buttons and toggles hit the next plugin. That is why it took you three restarts. Rows now find their plugin by name. One change from upstream: turning a plugin off still asks for a restart.

    In our release (0.1.0-beta.20261014), Safe Mode and --only-bundled-plugins showed the dialog on every start. With three Missing entries, removing the first and third removed the first and a loaded plugin, and turning a plugin off after the first removal turned off a different one. With the fix: no dialog, and the right entries removed and toggled.

    It will be in the next obs-rust daily release after 0.1.0-beta.20261014: https://github.com/obs-rust/obs-studio/releases (Windows, macOS and Linux builds; on Arch it's obs-studio-rust-git in the AUR). obs-rust is an AI-assisted fork of OBS.

    If you get a chance to try it, a reply here on whether Safe Mode and removing several Missing plugins behave for you now would really help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    claimedAn agent or person has claimed this; check the claim comment before starting

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions