agalwood/Motrix · error · AppError
PLUGIN_ACTIVATION_CAP_EXCEEDED
PLUGIN_ACTIVATION_CAP_EXCEEDED
Error message
active plugin cap (${this.maxActivePlugins}) reached What it means
Activation is refused once the number of active plugins reaches maxActivePlugins (default 32, configurable via PluginHostOptions.maxActivePlugins), throwing PLUGIN_ACTIVATION_CAP_EXCEEDED. The cap bounds simultaneous VMs.
Source
Thrown at src/core/plugin/host/plugin-host.ts:236
return promise
}
private async doActivate(pluginId: string): Promise<void> {
const indexed = this.opts.registry.get(pluginId)
if (!indexed) {
throw new AppError(
ErrorCode.PluginManifestInvalid,
`unknown plugin: ${pluginId}`
)
}
if (!indexed.state.enabled) {
throw new AppError(
ErrorCode.PluginRuntimeFault,
`plugin ${pluginId} is disabled`
)
}
if (this.active.size >= this.maxActivePlugins) {
throw new AppError(
ErrorCode.PluginActivationCapExceeded,
`active plugin cap (${this.maxActivePlugins}) reached`
)
}
const needsFfmpeg =
indexed.manifest.permissions.includes('ffmpeg') ||
(indexed.manifest.optionalPermissions ?? []).includes('ffmpeg')
let ffmpegDetection: FfmpegDetection = { available: false }
if (needsFfmpeg && this.opts.ffmpegDetect) {
ffmpegDetection = await this.opts.ffmpegDetect()
}
const ffmpegSatisfied =
ffmpegDetection.available &&
ffmpegSatisfies(
ffmpegDetection.version ?? '',View on GitHub (pinned to 1a708ee577)
Solutions
- Deactivate an idle or lower-priority plugin first, then retry activate.
- Wait for the idle sweep (5 min default) to reclaim VMs, or trigger it manually.
- Raise maxActivePlugins in PluginHostOptions if the environment can sustain more VMs.
Example fix
// before
await host.activate(id) // throws at cap
// after — make room first
if (host.activeCount >= host.maxActivePlugins) {
const idle = host.pickIdlePlugin()
if (idle) await host.deactivate(idle)
}
await host.activate(id) Defensive patterns
Strategy: fallback
Validate before calling
function assertCapAvailable(activeCount: number, max: number): void {
if (activeCount >= max) {
throw new Error(`active plugin cap (${max}) reached; deactivate an idle plugin first`)
}
} Type guard
function hasCapRoom(activeCount: number, max: number): boolean {
return activeCount < max
} Try / catch
try {
await host.activate(pluginId)
} catch (e) {
if (e.code === 'PLUGIN_ACTIVATION_CAP_EXCEEDED') {
const idle = host.pickIdlePlugin()
if (idle) { await host.deactivate(idle); await host.activate(pluginId) }
else throw e
} else throw e
} Prevention
- Deactivate idle or lower-priority plugins before activating new ones when near the cap.
- Expose and respect maxActivePlugins in the UI so users see the budget.
- Trigger the idle sweep before reporting the cap as a hard failure.
When it happens
Trigger: Activating one more plugin while active.size is already >= maxActivePlugins.
Common situations: Many plugins enabled at once; cap lowered for a constrained environment; idle plugins not yet swept by the 5-min idle timer; a burst of concurrent activations.
Related errors
- plugin.storage.quota_exceeded
- PluginActivationCapExceeded
- PLUGIN_MANIFEST_INVALID
- PLUGIN_RUNTIME_FAULT
- plugin.lifecycle.activation_capability_violation
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/9980230513ff58a0.
Report an issue: GitHub.