跳转到内容

故障排查与升级

tool-bridge 的错误通常落在五层之一:目标/网络、身份、路径授权、节点契约、provider/宿主。按层排查能避免把 404 当宕机、把上游 401 当本地 SK 错误,或为临时问题扩大权限。

在不泄露 Secret 的前提下记录:

  • BaseURL 的 host(不含 query/token);
  • 宿主类型和对应版本;
  • 当前 profile 名、SK id/owner(不含明文);
  • 请求 method/path、HTTP status、TBError code、retryable;
  • 节点 kind、工具名、schema digest/版本线索;
  • 时间、trace id、设备/plugin/remote 的公开标识;
  • 能否由最小只读请求复现。

不要粘贴 Authorization、Cookie、OAuth code/state、SecretStore 值、完整敏感 arguments、环境文件或 Cloudflare 资源凭证。

Terminal window
tb whoami
tb status --json
tb help --json
tb tree --depth 2 --json
TARGET_PATH=tools/docs
tb help "$TARGET_PATH" --json

如果 CLI 自身不可用,先用 HTTP:

Terminal window
curl -i https://tb.example.com/healthz
curl -i \
-H "Authorization: Bearer $TB_SK" \
-H "Accept: application/json" \
https://tb.example.com/~help

healthz 200 但 ~help 失败,说明进程存活但认证、bootstrap 或数据面仍有问题。

含义:Bearer 缺失、未知、disabled、deleted 或 expired。

检查:是否选错 profile/BaseURL;代理是否保留 Authorization;SK 是否被旋转;Workers KV 吊销/签发是否仍在传播窗口。不要改成 query token,也不要立即换 Admin SK 掩盖问题。

含义:路径确实不存在,或当前身份没有 read 而被可见性隐藏。

从最近可见父路径执行 tb help/tb tree;用管理员身份只做对照,不要让业务客户端依赖管理员结果。tb search 404 还可能仅表示宿主没有 Search capability。

身份有效且资源可见,但缺 callwriteregisteradmin。检查节点 ~help 声明的 scope、SK 的 allow/deny,以及 registerPaths。不要只添加一个宽泛 ** scope;修正最小动作和路径。

重新读取工具级 ~help --json 和当前 CLI --help。检查直连/信封形状、JSON object、路径占位、Context capability、Plugin export、remote host 写法。不要保留旧字段 fallback。

常见于 Context ifVersion 过期、注册路径被另一 key 占用或并发更新。重新读取权威状态,合并后重试;不要直接删除他人节点或覆盖版本。

读取 retryable,指数退避并限制总时长。Feedback 每 owner/path 也有防刷限制。不要并发洪泛或无上限重试。

区分消息来源:设备 offline、Secret 无法解析、上游网络、Plugin disabled、对象存储未装配、remote 环/跳数、未实现 capability。retryable 为 false 时先修配置;为 true 时仍要有退避和截止时间。

使用最小无敏感请求复现,保留时间/trace/版本,检查服务日志中的结构化错误。不要把完整 payload 或 headers 打开到 debug 日志。

正常发现流程与 Feedback/Search 的分工见发现、反馈与协作

症状:Search 404,但树正常。

根级 POST /~search 是可选宿主能力。使用 tb tree、父路径 tb help;Cloudflare Deploy Button 模板与完整源码部署的 bindings 可能不同,以实际 ~help/宿主配置为准。

症状:Search 找到旧工具或找不到新工具。

Search 是派生索引。直接读取节点/工具 ~help 判断权威工具表;确认节点仍存在且当前 SK 有 read+call。必要时按对应版本管理入口重建/刷新,不要直接修改 D1/SQLite 索引表。

先复核密钥、出站身份与安全边界,不要用扩大本地 SK 或匿名降级掩盖上游凭证错误。

症状:错误提到 authRef/skRef 无法解析。

Terminal window
tb secret ls

确认引用名存在,但不要尝试读取明文。检查部署是否正确注入 32 字节 base64url 加密主密钥;主密钥错误会使已有密文不可解。声明引用后必须 fail closed,不能删掉 authRef 让请求匿名出去。

症状:挂载时 permission_denied。

绑定任何 authRef/skRef 除目标路径 register 外,还要求 system/secret:admin。这是防止受限注册者借用平台已有 Secret 的安全门。

症状:上游 401/403。

区分本地 HTTP status 与归一后的上游错误。检查 auth header/scheme、凭证过期和上游 scope;本地调用者 SK 永远不应透传上游。

任务步骤分别见使用内置集成目录注册外部 Plugin

catalog 找不到 provider:当前宿主没有打包它,改用其他接入方式,不复制别的实例 catalog。

Plugin health 正常但注册失败~describe 的 protocolVersion、exports、auth、methods/capabilities 或重复 id 不合法。healthz 只检查生命周期端点,不证明 descriptor 合法。

Plugin 注册成功但调用 unavailable:检查 enabled、transport token、endpoint TLS、binding 是否由宿主装配,以及挂载业务 authRef。transport token 与上游 token 不得混用。

多 export 选错:用 tb plugin get <id>tb integration catalog --json 查看逐 export profile;tools/v1 用 tool 节点,context/v1 用 Context 节点。

回滚时先卸载引用节点,再注销 Plugin,最后确认无引用后删除 Secret。

先确认当前是在排查上游挂载还是入站投影;两个方向的完整流程见挂载 MCP 与 MCP 客户端投影

先确定故障方向:

  • 上游挂载:tb help <mcp-node> 是否能 discovery,OAuth/authRef 是否有效;
  • 入站投影:MCP client 是否连接 /<base>/~mcp,每次请求是否带 scoped SK。

MCP 客户端里的工具名可能是编码后的名称,以 tools/list 为准。tb_search 缺失只表示宿主未启用 Search。上游返回 isError:true 可以是 HTTP 200 的业务错误,不等同于传输失败。

OAuth 问题检查 canonical origin、redirect allowlist 和实际访问域名;上游只接受 loopback 时按当前 tb tool auth --help 判断 --local 是否适用。

工具表、凭证与验证步骤见把 HTTP API 声明为工具

路径参数缺失时比较 pathTemplate{name} 与 arguments/schema。GET/DELETE 剩余参数进 query,POST/PUT 进 JSON body。复杂签名、响应转换或供应商错误语义无法由简单工具表表达时,迁移为 Plugin,不要继续堆静态 header 或隐藏约定。

公网 endpoint 被拒时改用 HTTPS。TB_ALLOW_INSECURE_HTTP 只用于本地测试,不作为生产修复。

Provider capability、乐观并发和 $ref 边界见挂载与使用 Context

unknown cmd:该 provider 没有相应 handler/capability;重新读 namespace ~help

写入 403:缺 write 或节点 readOnly。不要因为 CLI 有 ctx put 就假设所有 Context 可写。

conflict:重新 Get 最新 version,再合并重试。

$ref 404/过期:重新 Get 获取新短期 URL;检查节点是否仍存在、TTL 是否过期、对象是否被删除。

R2 provider unavailable:宿主没有注入 ObjectStore 或加密 key 无法生成中转 token。修宿主装配,不改业务 schema。

Terminal window
tb device ls
DEVICE_ID=build-01
tb tree "device/$DEVICE_ID" --depth 3

设备 SK、Shell/文件白名单与容器模式见Device 反向连接

连接拒绝时检查 register scope、registerPaths、mountPath、URL/hello deviceId 一致。反复重连检查反向代理 WebSocket upgrade、Authorization 和网络 idle timeout。

Shell 默认 allowlist 为空;所有命令拒绝是安全默认。Sidecar 看不到文件时确认双方挂同一个 volume。调用 503 retryable 表示 offline,可以退避等待重连;不要高频轮询或自动改成 --allow '*'

紧急处置先 disable Device SK,再停止进程,最后通过 registry 管理面处理遗留 offline 节点。

双层身份、host allowlist、skRef 与 Via 保护见Federation 连接多棵树

remote baseUrl 不在白名单 时先检查:

Terminal window
tb federation ls --json

allowlist 需要裸 host suffix;env 基线不可通过 API 删除。skRef 失败按 SecretStore 排查。本地 403/404 与远端权限是两层问题,分别用本地 SK 和远端专用 SK 验证。

环/跳数错误表示拓扑有问题,不要先无限提高 maxHops。远端路径、tree/help 响应被当作不可信数据;路径不规范也会得到不可用错误。

浏览器身份、本地存储和同源代理要求见使用 Dashboard

/ui/ 404 通常是 assets 未部署或代理路径错误。页面能加载但 API 401 是浏览器会话/SK 问题。深链刷新失败时只为 /ui/* 配 SPA fallback,不能吞根 ~help~mcp、POST 数据面或 system/*

共享电脑使用后清理该 origin 的站点数据;怀疑泄露时立即 disable/rotate SK。

先确认实际采用的是一键部署还是完整源码部署,两者的 D1/Search 资源不同。

  • KV 的认证/注册读可能有最终一致窗口;
  • 检查 KV/R2/D1/DO/Assets bindings 是否与部署方式一致;
  • 自定义域与 canonical origin 必须一致;
  • 部署仓库配置不应包含账户 ID、资源 ID 或 secret;
  • 不要把官网 Pages 部署和网关 Worker 部署混淆。

持久卷、反向代理、备份与恢复步骤见部署 Node / Docker

  • /data 必须可写且持久;
  • 首次启动缺 TB_BOOTSTRAP_ADMIN_SK 会 fail closed;
  • TB_ALLOW_INSECURE_BOOTSTRAP=true 只用于一次性本地开发;
  • 反向代理保留 WebSocket、Authorization、host/proto;
  • SQLite/文件备份应在升级前完成并验证恢复。
  1. 停止新流量或切回旧路径;
  2. 禁用新节点/Plugin/Device 身份,而不是立刻删全部状态;
  3. ~help 和最小 read-only 调用验证旧路径;
  4. 卸载新节点;
  5. 确认没有引用后再删除 Plugin、allowlist、Secret;
  6. 对远端/OAuth 凭证在上游侧完成撤销;
  7. 保存不含 Secret 的证据和对应版本。

项目处于 pre-launch,升级前阅读发布说明并备份状态。不要依赖隐藏旧 flag、旧 wire fallback 或临时共享部署的状态。

升级不是“换一个 tag 后看 /healthz”。每次升级都应重新证明身份、权限、真实 Provider 与恢复路径仍然成立。

  1. 记录当前宿主、版本或 commit、BaseURL 与不含 Secret 的资源清单;
  2. 阅读目标版本 release notes,识别用户可感知和存储变化;
  3. 限制写入,并备份权威状态、对象数据与 SecretStore 加密根;
  4. 保留旧镜像、旧 commit 或上一 Worker version,明确回滚目标;
  5. 在隔离或预览环境部署目标版本;
  6. 用 Admin SK 验证根 ~help、status 和实际 capability;
  7. 用受限 SK 验证 allow/deny/404,并完成一个无破坏性的真实 Provider 调用;
  8. 验证 Dashboard,以及启用时的 Search、MCP、Device 和 Federation;
  9. 切换正式流量,并观察结构化错误与上游健康;
  10. 失败时停止新流量,恢复权威状态和旧版本,再重复最小 smoke。
  • Node / Docker:按部署 Node / Docker停止写入、备份整个 /data、固定旧/新镜像并演练卷恢复;
  • Cloudflare:按源码部署核对 KV/R2/D1/DO/Assets 与构建产物;一键模板按其生成仓库和一键部署说明升级,不要混用资源表;
  • 嵌入式 SDK:按嵌入现有应用随宿主应用升级,重点验证自定义 StateStore/ObjectStore、Plugin catalog/bindings 与 fetch/connect
  • 所有宿主:切流前重新执行生产上线检查清单

如果目标版本无法读取旧状态、原加密根不可用或真实 Provider smoke 失败,不要用重新 bootstrap、删除索引或扩大 Admin 权限绕过。先回滚并保存脱敏证据,再根据对应版本发布说明处理迁移。

准备一份最小报告:宿主/版本、无敏感的复现命令、status/code/retryable、期望与实际、相同 SK 的父路径 ~help 结果、是否可在本地/另一宿主复现。源码问题可提交到 tool-bridge GitHub,提交前再次清除 token、URL query 和业务数据。