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

  1. Check availability before use: read `DevSidecar.status.plugin.<key>.enabled` and skip/stub the call when it is false.
  2. Install/use the full Node-based package (pnpm workspace install) where all plugin modules are present, rather than the SEA binary.
  3. If you own the build, ensure the plugin directory is included in the SEA asset bundle so `modules.plugin[key]` is not null.
  4. 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

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.