{"record":{"id":"ba8b7c62611d0885","repo":"docmirror/dev-sidecar","slug":"key-ba8b7c","errorCode":null,"errorMessage":"插件【${key}】不可用，无法启动","messagePattern":"插件【(.+?)】不可用，无法启动","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/core/src/expose.js","lineNumber":41,"sourceCode":"  config.addDefault(key, pluginConfig)\n  if (pluginStatus) {\n    lodash.set(status, key, pluginStatus)\n  }\n  return api\n}\n\nconst proxy = setupPlugin('proxy', modules.proxy, context, config)\nconst plugin = {}\nfor (const key in modules.plugin) {\n  const target = modules.plugin[key]\n  if (target == null) {\n    // 插件不可用（如 SEA 独立可执行文件中无法携带 free-eye），注册为禁用状态\n    log.warn(`插件【${key}】不可用，已注册为禁用状态`)\n    const stub = {\n      config: { key, enabled: false },\n      status: { enabled: false },\n      plugin: () => ({\n        start: async () => log.warn(`插件【${key}】不可用，无法启动`),\n        stop: async () => {},\n        close: async () => {},\n        run: async () => { throw new Error(`插件【${key}】不可用`) },\n      }),\n    }\n    const stubApi = setupPlugin(`plugin.${key}`, stub, context, config)\n    plugin[key] = stubApi\n    continue\n  }\n  const api = setupPlugin(`plugin.${key}`, target, context, config)\n  plugin[key] = api\n}\nconfig.resetDefault()\nconst server = modules.server\nconst serverStart = server.start\n\nfunction newServerStart ({ mitmproxyPath }) {\n  return serverStart({ mitmproxyPath, plugins: plugin })","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/docmirror/dev-sidecar/blob/7710cd56cce760c708f30b01d2d4056eb8c402d5/packages/core/src/expose.js#L23-L59","documentation":"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】不可用'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait DevSidecar.plugin.start('free-eye')\n// after\nconst p = DevSidecar.plugin.get('free-eye')\nif (p && p.status.enabled !== false) await DevSidecar.plugin.start('free-eye')\nelse console.warn('free-eye unavailable in this build')","handlingStrategy":"fallback","validationCode":"const stub = DevSidecar.plugin?.get?.(key)\nif (!stub || stub.status?.enabled === false) {\n  console.warn(`plugin ${key} disabled/unavailable, not starting`)\n  return\n}","typeGuard":"function canStart(pluginEntry) {\n  return pluginEntry != null && pluginEntry.status?.enabled !== false && typeof pluginEntry.plugin === 'function'\n}","tryCatchPattern":"try {\n  await plugin.start(key)\n} catch (e) {\n  if (/不可用|无法启动/.test(e.message)) {\n    console.warn(`plugin ${key} unavailable in this build, continuing without it`)\n  } else {\n    throw e\n  }\n}","preventionTips":["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."],"tags":["plugin","stub","sea","unsupported-operation"],"backgroundTag":"plugin-module-unavailable","analyzedSha":"7710cd56cce760c708f30b01d2d4056eb8c402d5","analyzedAt":"2026-08-31T22:07:07.234Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}