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
- Fix the plugin's original startup failure so rollback is never needed.
- Restart the gateway after such a warning to reclaim any leaked resources.
- Report/update the backend owner implementation whose stopOwner threw (the message includes the cause).
- 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
- Restart the gateway after rollback warnings to reclaim leaked resources
- Fix failing plugin startup to avoid rollback paths
- Avoid hot-reloading broken plugin configs
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
- [plugin:${pluginConfig.id}] Disabled after startup failure:
- [plugin:${pluginId}] Rollback stop hook failed: ${formatErro
- [backend:${ownerId}] SQLite store close failed: ${formatErro
- [plugin-marketplace] Failed to fetch marketplace from ${url}
- [plugin-marketplace] Failed to load marketplace entry: ${for
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/91674a361fea638e.
Report an issue: GitHub.