排错指南

常见错误码、报错现象与修复步骤。

插件开发中遇到的大部分问题可以归为四类:清单校验失败权限被拒视图/协议错误会话与运行时失效。本节按"现象 → 原因 → 修复"组织,先看错误码速查表,再按分类定位。

错误码速查

错误码 / 异常属于一句话含义
permission_denied宿主响应未声明所需权限
unknown_command宿主响应当前插件类型/IDE 不支持该 SDK 命令
invalid_context宿主响应信封不属于当前插件会话(会话已过期)
manifest_*清单校验plugin.toml 存在结构或语义错误
delivery_paused宿主响应插件连续失败,视图补丁投递被暂停
view_not_mounted / component_not_found / method_not_supported / invalid_arguments / operation_failed宿主响应组件命令式调用失败
ViewProtocolError本地异常快照/补丁超过上限或视图已关闭
StaleReferenceError本地异常运行时重启后使用了已经失效的 runtime 引用
RuntimeUnavailableError本地异常当前后端不支持运行时检查
SymbolResult.stale业务结果符号请求期间文档修订发生变化
TransportClosedError本地异常传输层已关闭(插件已卸载/会话结束)
PluginContextError本地异常宿主注入的上下文缺失或非法

区分两类错误:宿主拒绝的请求通过回调 error= 收到(SdkApiError 子类);本地就能判断的问题在调用处直接抛出异常。详见 错误体系

插件无法启动或激活失败

manifest 校验报错

插件安装 / 打包时会在插件详情页显示错误码。常见取值与修复:

错误码含义修复
manifest_missing找不到 plugin.toml确认文件在插件目录根
manifest_invalid_tomlTOML 语法错误检查括号、引号
manifest_unsupported_versionmanifest_version 不是 2改为 manifest_version = 2
manifest_invalid_plugin_id插件 ID 不合法仅用小写字母、数字、-_
manifest_invalid_contribution_id贡献 ID 未使用 插件ID. 前缀或重复统一改为 id = "<插件ID>.<名称>" 且全局唯一
manifest_invalid_activation_event激活事件目标不是本插件贡献的 ID检查 onView: / onCommand: 目标
manifest_invalid_permission权限名不存在对照 Manifest 权限表 修正
manifest_invalid_whenwhen 表达式语法错误用文档列出的上下文键重写

激活事件没命中

插件已安装但从不启动,通常是因为触发的事件与 activation_events 不匹配:

  • 视图插件需要在 activation_events 里声明 onView:<viewId>;只在清单里声明视图贡献(contributes.views不会让插件自动启动。
  • 命令插件需要 onCommand:<commandId>
  • 想让插件在 IDE 启动时就运行,声明 onStartup(Ui/Service)或使用 DataPlugin。

启动钩子抛异常

on_start() 抛出的异常会让宿主把插件标记为 failed 并停止会话。检查 IDE 输出面板中的 traceback;常见原因包括在 on_start 里访问了未声明的权限、视图 ID 写错、或试图同步等待回调结果。

权限被拒(permission_denied)

调用 API 时收到 PermissionDeniedError

def on_result(error=None, **cb):
    if isinstance(error, PermissionDeniedError):
        print("缺少权限:", error.required_permission)

self.file.read_file("/boot.py", callback=on_result)

修复步骤:

  1. error.required_permission 确认缺哪个权限(例如 file.read)。
  2. plugin.tomlpermissions 列表里补上,重新打包并重装插件——清单是在安装时解析的,只改文件不重装不会生效。
  3. 权限默认拒绝:不要假设"既然是 UI 插件就自动有文件权限"。

视图不显示或渲染异常

现象原因修复
视图空白view_id 与贡献 ID 不一致两边统一为 id(如 device-console.status
视图空白未声明 ui.view 权限补权限并重装
视图空白视图模型创建后没 open()调用 view.open()
一直转圈(环形指示器不停)手动传的 instance_id 与宿主挂载点不一致,快照发到了没人渲染的实例侧边栏视图直接用 self.views.create(view_id) 不传 instance_id(SDK 会按 manifest 默认成 container:<容器 id> 对齐宿主);标签页视图用 tabs.create_view 回调里的 instance.instance_id
数据没出现数据在 on_start 返回后才异步送达用回调接力,别在 on_start 里顺序等待
补丁被暂停delivery_paused插件近期有大量失败帧;检查代码,等待 IDE 恢复投递后自动 resync

ViewProtocolError(本地抛出)

快照/补丁超过硬性上限时,会在发送前本地抛出

  • 单次快照节点数 > MAX_SNAPSHOT_NODES(20000)
  • 单次补丁操作数 > MAX_PATCH_OPS(2000)
  • 快照/补丁负载 > MAX_VIEW_PAYLOAD_BYTES(2MB)

修复:分页发送(如 VirtualListitem_count + on_request_range,或 TreeViewon_request_children),不要一次性推送全部数据。

回调不执行或结果为空

  • 没有处理回调中的 error:失败响应会以 error 关键字传入,cb 里没有业务字段。请显式检查 cb.get("error"),不要用 if cb 判断成功。
  • 没传 callback:即发即弃方法(如 self.editor.set_text)立即返回、没有回调;需要结果的 API 才传 callback
  • 回调里做了阻塞操作:回调运行在 Bridge 事件循环线程,time.sleep 或同步 IO 会卡住整个插件。
  • 事件订阅被拒:主题未知或权限不足时订阅在本地被丢弃,通过 callback(error=...) 感知。

会话与运行时失效

InvalidPluginContextError(invalid_context

会话已过期:通常是 IDE 端重启了会话或运行时,而插件仍有属于前一会话的请求在途。重新获取当前上下文后再发起请求。

StaleReferenceError / RuntimeUnavailableError

运行时后端重启后,已有的 runtime.* 引用全部失效:

  • StaleReferenceError — 使用了重启前的对象引用。
  • RuntimeUnavailableError — 当前后端不支持运行时检查(能力不可用)。

修复:订阅 runtime.backend.restartedself.runtime.on_backend_restarted),在回调里重新枚举会话 / 重建视图。

SymbolResult.stale

documents.symbols() 返回的 SymbolResult.staleTrue,表示文档在符号请求期间发生了变化。这是正常业务结果,不会抛出本地异常。重新获取当前文档及其修订号后再请求符号。

TransportClosedError

传输层已关闭:插件被卸载、停用或运行时重启。属于预期清理路径,把该异常当作"会话结束"处理,不要阻塞退出。

插件卡死或无法再次启停

单例解释器共享同一个运行时。如果一个插件没有正常退出(例如后台线程不结束、on_dispose 抛异常),会阻塞该插件(甚至影响其他插件)的启停。

处理办法:

  1. 在 IDE 运行时管理里"重启运行时"整体恢复。
  2. 根因排查:确认后台任务在 on_dispose 里被取消、DataPlugin 用 run_once() 而非 start()

单例解释器的全局状态污染

所有插件共享同一个 Python 解释器:

  • 模块级 / 全局变量在插件间可见,务必用 插件ID. 前缀命名空间。
  • 插件内用 __main__ 模块名或全局单例的代码可能与其他插件冲突。
  • 需要隔离时,尽量把状态放在 Plugin 实例属性里,而不是模块全局。

快速定位流程

报错了吗?
├─ 是清单校验错(manifest_*)→ 见「manifest 校验报错」
├─ 是回调里的 error → 看 error.code:
│    ├─ permission_denied → 补权限
│    ├─ unknown_command → 检查插件类型/命令 ID
│    ├─ invalid_context → 会话过期,重试
│    └─ 其他 SdkApiError → 按 message 定位
├─ 是本地异常:
│    ├─ ViewProtocolError → 检查视图负载上限
│    ├─ StaleReference/RuntimeUnavailable → 重启后重建引用
│    └─ TransportClosed → 会话已结束,正常
└─ 没有报错但功能不对 → 检查激活事件 / 权限 / 视图 ID / 回调时序

On this page