docmirror/dev-sidecar · warning
插件【${key}】不可用,无法启动
Error message
插件【${key}】不可用,无法启动 What it means
Warning logged by the stub plugin's start() when someone tries to start a plugin that was registered as unavailable. The stub was created in expose.js because the real plugin module was null (e.g. free-eye missing in SEA builds). Calling start() is a no-op that only logs; calling run() on the stub throws '插件【key】不可用'.
Source
Thrown at packages/core/src/expose.js:41
config.addDefault(key, pluginConfig)
if (pluginStatus) {
lodash.set(status, key, pluginStatus)
}
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 })View on GitHub (pinned to 7710cd56cc)
Solutions
- Don't start the plugin: check plugin availability/status first and skip start for plugins whose status.enabled is false.
- If you need free-eye, run the full install (normal Node deployment) instead of the SEA executable.
- If run() is required, expect it to throw '插件【key】不可用' — wrap in try/catch and treat as unsupported in this environment.
- Restore the missing plugin module/dependencies so expose.js registers the real plugin instead of the stub.
Example fix
// before
await DevSidecar.plugin.start('free-eye')
// after
const p = DevSidecar.plugin.get('free-eye')
if (p && p.status.enabled !== false) await DevSidecar.plugin.start('free-eye')
else console.warn('free-eye unavailable in this build') Defensive patterns
Strategy: fallback
Validate before calling
const stub = DevSidecar.plugin?.get?.(key)
if (!stub || stub.status?.enabled === false) {
console.warn(`plugin ${key} disabled/unavailable, not starting`)
return
} Type guard
function canStart(pluginEntry) {
return pluginEntry != null && pluginEntry.status?.enabled !== false && typeof pluginEntry.plugin === 'function'
} Try / catch
try {
await plugin.start(key)
} catch (e) {
if (/不可用|无法启动/.test(e.message)) {
console.warn(`plugin ${key} unavailable in this build, continuing without it`)
} else {
throw e
}
} Prevention
- Filter plugin start lists by status.enabled before starting.
- Don't blindly start all plugins in SEA/standalone environments.
- Persisted plugin state from a full install may not apply to SEA builds — reconcile on startup.
- Prefer run() only after confirming the plugin is a real module, not a stub.
When it happens
Trigger: Calling plugin.start(key) (or the GUI/plugin manager invoking start) for a plugin that was replaced by the unavailable-stub — typically free_eye after its module failed to load in a SEA executable or broken install.
Common situations: User toggles the free-eye (护眼) plugin on in the GUI while running the standalone SEA build; a script or automation tries to start all plugins indiscriminately; plugin state persisted from a previous full install is re-applied in an environment where the plugin no longer exists.
Related errors
AI-assisted analysis of docmirror/dev-sidecar@7710cd56cc (2026-08-31).
Data as JSON: /api/errors/ba8b7c62611d0885.
Report an issue: GitHub.