docmirror/dev-sidecar · warning
插件【${key}】不可用
Error message
插件【${key}】不可用 What it means
When a bundled plugin module (e.g. free-eye) cannot be loaded — typically because it is missing inside a SEA single-executable build — dev-sidecar registers a disabled stub instead of the real plugin. The stub's `run()` (and every other lifecycle call) throws `插件【key】不可用` to make it explicit that the plugin functionality is not available in this installation. It is a deliberate guard, not an unexpected failure.
Source
Thrown at packages/core/src/expose.js:44
}
return api
}
const proxy = setupPlugin('proxy', modules.proxy, context, config)
const plugin = {}
for (const key in modules.plugin) {
const target = modules.plugin[key]
if (target == null) {
// 插件不可用(如 SEA 独立可执行文件中无法携带 free-eye),注册为禁用状态
log.warn(`插件【${key}】不可用,已注册为禁用状态`)
const stub = {
config: { key, enabled: false },
status: { enabled: false },
plugin: () => ({
start: async () => log.warn(`插件【${key}】不可用,无法启动`),
stop: async () => {},
close: async () => {},
run: async () => { throw new Error(`插件【${key}】不可用`) },
}),
}
const stubApi = setupPlugin(`plugin.${key}`, stub, context, config)
plugin[key] = stubApi
continue
}
const api = setupPlugin(`plugin.${key}`, target, context, config)
plugin[key] = api
}
config.resetDefault()
const server = modules.server
const serverStart = server.start
function newServerStart ({ mitmproxyPath }) {
return serverStart({ mitmproxyPath, plugins: plugin })
}
server.start = newServerStart
async function startup ({ mitmproxyPath }) {View on GitHub (pinned to 7710cd56cc)
Solutions
- Check availability before use: read `DevSidecar.status.plugin.<key>.enabled` and skip/stub the call when it is false.
- Install/use the full Node-based package (pnpm workspace install) where all plugin modules are present, rather than the SEA binary.
- If you own the build, ensure the plugin directory is included in the SEA asset bundle so `modules.plugin[key]` is not null.
- Guard your caller with try/catch so the stub throw degrades gracefully instead of crashing the automation.
Example fix
// before
await DevSidecar.plugin['free-eye'].run(options)
// after
if (DevSidecar.status.plugin['free-eye']?.enabled) {
await DevSidecar.plugin['free-eye'].run(options)
} else {
log.warn('free-eye plugin unavailable in this build; skipping')
} Defensive patterns
Strategy: try-catch
Validate before calling
// check plugin availability before calling
const enabled = DevSidecar.status?.plugin?.['free-eye']?.enabled
if (!enabled) throw new SkipError('plugin unavailable in this build') Type guard
function isPluginAvailable (devSidecar, key) {
return Boolean(devSidecar?.status?.plugin?.[key]?.enabled) &&
typeof devSidecar.plugin?.[key]?.run === 'function'
} Try / catch
try {
await DevSidecar.plugin[key].run(options)
} catch (err) {
if (String(err.message).includes('不可用')) {
log.warn(`plugin ${key} unavailable; skipping`)
} else {
throw err
}
} Prevention
- Check status.plugin.<key>.enabled before every plugin call
- Prefer the full Node install over SEA binaries when plugins are required
- Wrap plugin automation in guards that treat unavailable plugins as skippable
- Log plugin availability at startup of your integration
When it happens
Trigger: Calling `DevSidecar.plugin.<key>.run(...)` (or start/stop on the stub) for a plugin whose module was null at registration time in packages/core/src/expose.js:32-50 — most commonly running the packaged SEA binary where the free-eye plugin assets are not embedded.
Common situations: Running the standalone executable instead of the full Node install; a partially broken install where a plugin module fails to require; scripts/automation that unconditionally calls plugin APIs without checking `status.plugin.<key>.enabled`.
Related errors
AI-assisted analysis of docmirror/dev-sidecar@7710cd56cc (2026-08-31).
Data as JSON: /api/errors/e5d1e795aafa1ca5.
Report an issue: GitHub.