musistudio/claude-code-router · warning

[plugin:${pluginId}] Rollback resource cleanup failed: ${for

Error message

[plugin:${pluginId}] Rollback resource cleanup failed: ${formatError(error)}

What it means

The final step of plugin-load rollback calls backendService.stopOwner(pluginId) to release the plugin's owned resources (SQLite stores, servers). If that call itself throws, this warning is logged and rollback ends; the process stays up but the plugin's backend resources may leak until restart.

Source

Thrown at packages/core/src/plugins/service.ts:923

    this.gatewayRoutes = snapshot.gatewayRoutes;
    this.providerAccountConnectors = snapshot.providerAccountConnectors;
    this.proxyRoutes = snapshot.proxyRoutes;
    this.resourceOwnerIds = snapshot.resourceOwnerIds;
    this.stopHooks = snapshot.stopHooks;
    this.virtualModelProfiles = snapshot.virtualModelProfiles;

    for (const stopHook of newStopHooks) {
      try {
        await stopHook.stop({ reason: "disabled" });
      } catch (error) {
        console.warn(`[plugin:${pluginId}] Rollback stop hook failed: ${formatError(error)}`);
      }
    }

    try {
      await backendService.stopOwner(pluginId);
    } catch (error) {
      console.warn(`[plugin:${pluginId}] Rollback resource cleanup failed: ${formatError(error)}`);
    }
  }
}

export const pluginService = new GatewayPluginService();

function pluginPermissionAccess(pluginConfig: Pick<GatewayPluginConfig, "enabled" | "id" | "permissions">): PluginPermissionAccess {
  const permissions = pluginConfig.permissions
    ?? knownGatewayPluginDefaultPermissions(pluginConfig.id)
    ?? (pluginConfig.enabled === true ? undefined : [...GATEWAY_PLUGIN_PERMISSION_IDS]);
  return {
    explicit: permissions !== undefined,
    permissions: new Set(permissions ?? []),
    pluginId: pluginConfig.id
  };
}

function pluginPermissionList(access: PluginPermissionAccess): GatewayPluginPermission[] {

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Fix the plugin's original startup failure so rollback is never needed.
  2. Restart the gateway after such a warning to reclaim any leaked resources.
  3. Report/update the backend owner implementation whose stopOwner threw (the message includes the cause).
  4. Avoid config hot-reloads of the broken plugin until fixed.
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Rollback of a failed plugin load where stopOwner throws — e.g. an owned child process or store refuses to stop, or cleanup logic throws outside the per-store try/catch seen in stopOwner.

Common situations: Plugin that spawns processes/opens stores and fails startup; repeated config reloads accumulating leaked resources; a backend owner type with buggy teardown.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/91674a361fea638e. Report an issue: GitHub.