Files
pikasTech-unidesk/.agents/skills/unidesk-sub2api/references/troubleshooting-accounts.md
T
pikastech 31106a2ee0
Pipelines as Code CI / hwlab-web-probe-sentinel-nc01- Success
Pipelines as Code CI / platform-infra-gitea-nc01- Success
Pipelines as Code CI / unidesk-host- Success
chore: 合并并行工作区更新
2026-07-18 05:36:52 +02:00

64 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 账号池排障
### 客户可见错误与配置调优
1. 先用 `runtime errors --since <window>` 获取全账号同窗口证据:
- 以 Sub2API 原生 dashboard overview 的请求分母、客户错误率和上游错误率为主。
- 以 account availability、concurrency 和 upstream errors 解释账号可用性、排队、状态码与根因。
- 内部 monitor 使用真实 API key 和正式入口产生的错误必须纳入正式错误率、账号归因、trace 和调优判断;只单独标注调用方类别,不得因其不是外部客户而剔除或降级为测试噪声。
- 原生 system-log 索引缺少策略事件时,才使用 target runtime 日志补临时不可调度、failover、`account_select_failed``forward_failed`,并保留 fallback 披露。
2. 从客户可见错误中选有限 request id 运行 `trace`,按请求链区分:
- 上游失败后成功切号。
- 切号后候选耗尽。
- 首次选号即无候选。
- HTTP 200 已提交流式响应后出现 `forward_failed` 的 degraded 请求。
3. 规则证据必须同时包含真实 HTTP 状态码与响应体关键词:
- 只有状态码、通用包装文案或推断出的原因不能扩展关键词。
- 只有 `account_temp_unschedulable` 才证明规则命中;不能用相同状态码再次出现来推断规则失效。
- 优先使用精确短语,避免把 `context window`、认证失败、模型不支持等不可互换错误混入通用不可用规则。
4. 无候选或模型路由错误使用现有正式只读入口:
- `runtime get --account <selector>` 读取账号配置和调度状态;`runtime errors --account <selector> --full` 读取原生 Ops 已观测模型证据。
- 配置声明与已观测模型必须分开报告,不能把历史请求模型误当作实时上游能力。
- 没有账号真实支持目标模型时,保持池不声明该模型并快速失败,不映射到名称相近的其他模型。
- 没有原生实时能力接口时只能标记证据不足,不能据此补映射。
5. 调优按所有权下发:
- 非 auth 上游错误优先抽象为通用临时不可调度模板:
- 规则同时使用真实状态码和已证实的稳定响应短语;
- 先从当前 Sub2API 源码确认规则命中会在响应提交前触发当前请求 failover;
- 禁止在模板、CLI 或源码中硬编码账号名称、账号 ID、provider URL 或分组特例;
- 禁止用通用 400、通用 `invalid request` 或宽泛关键词覆盖真实客户参数错误;
- auth、token revoked、余额不足、分组删除和凭据失效使用专门的认证与账号状态路径,不混入通用非 auth 模板;
- 通用模板先修改 owning YAML,并保持冷却保守;默认从一分钟开始,没有新证据和明确授权不得超过三分钟。
- YAML-managed 账号走 `sync`runtime-manual 账号走显式 `runtime apply|delete`
- 多账号使用 `--accounts` 精准集合;例外账号从 selector 中显式排除,不使用隐式全量操作。
- 先 dry-run 核对 change、before/after 和账号集合,再加 `--confirm`,最后逐账号 `get` 或批量 noop dry-run 对账。
6. 不把当前并发快照当作错误时并发:
- 只有错误原文明确指向 concurrency,或存在错误时历史并发证据,才把降低上游并发作为有界对照实验。
- 缺少直接证据时先处理主导上游根因。
7. 下发后立即拉短窗口只做回归检查:
- 效果判定必须等待新的完整窗口。
- 同时比较请求分母、客户错误率、上游错误率、规则命中、切号成功、候选耗尽和 degraded 流式请求。
8. 版本回退必须有源码差异或版本对照证据证明当前版本引入回归:
- 旧版具有同一选择或错误传播逻辑时,不用回退替代配置治理。
- 新版包含相关 failover 修复时,优先保留新版并治理真实根因。
- Codex pool 哨兵、账号冻结/恢复、marker-only 判断或 probe 周期看不清:第一步跑 `bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-report`。这个报表是主观察面;只有报表缺字段或需要底层证据时,才继续看 `--raw`、CronJob log、state ConfigMap 或 Sub2API 管理 UI。若看到“临时不可调度状态”且包含规则序号/匹配关键词,检查 Sub2API `account_temp_unschedulable` 日志和账号 `temp_unschedulable_*` 字段;sentinel 只解释 `schedulable=false` 的 active quarantine,不解释这类内置临时冷却。
- 只加强监控、不让哨兵自动冻结账号时,把 YAML `sentinel.actions.enabled=false``codex-pool sync --confirm`。此时 marker probe 和 gateway failure monitor 仍记录 `would-freeze` / observe-only 证据,但不会通过 Sub2API admin 写 `schedulable=false``/responses/compact``codex.remote_compact.failed` 和 compact 上游 5xx failover 只作为 `gateway-compact-*` 观察事件记录,不作为哨兵自动切换触发器。
- 单个 request id 报 502/503/中断/没有自动切号:第一步跑 `bun scripts/cli.ts platform-infra sub2api codex-pool trace --request-id <requestId>`。先看 `outcome``reason``FAILOVER``SELECT-FAILED``ACCOUNT SIGNALS``WINDOW STATS`;只有 trace 报表缺字段或需要审计原始日志时,才加 `--show-lines``--raw`。若 `reason=failover-attempted-no-candidate`,说明切号动作已发生,但 scheduler 在排除失败账号后没有可用候选;继续用 `sentinel-report``validate --full` 区分 sentinel quarantine、request-path temp-unschedulable、账号 status 或容量耗尽。
- profile invalid:先修 `~/.codex/config.toml.<profile>``base_url``wire_api``model``auth.json.<profile>` 的 API key;不要在 YAML 中写密钥。
- 手动 OAuth/API-key 账号的 WebUI account test 连 `chatgpt.com` 超时,但目标运行面显式 HTTP proxy 探针可通:不要只看 Pod 或容器环境变量,按“受保护手动账号代理与分组绑定”小节确认 `manualAccounts.protected[].proxyBinding`,跑 `codex-pool sync --target <id> --confirm` 后再用原账号测试复测。若复测不再 reset/timeout,而是 `gpt-5.2-pro` 这类指定模型返回 ChatGPT OAuth Codex 不支持的能力错误,用默认/受支持模型或统一 key smoke 验证代理,不要把模型错误当作代理仍坏。
- 手动 OAuth/API-key 账号 WebUI account test 正常,但 PC Codex 客户端通过统一 key 访问 `/responses` 返回 503 且 trace 是 `account-select-failed` / `no available accounts`:按“受保护手动账号代理与分组绑定”小节确认该账号已绑定统一 key 使用的 pool group。WebUI group 列表和账号详情不一定足以证明 scheduler 可调度;必要时核对 admin account availability 与 `account_groups` join。k3s target 和 PK01 host-Docker target 都通过 `codex-pool sync --target <id> --confirm` 后用 `codex-pool validate --target <id> --full` 复测统一 key;如果 `MANUAL=N` 指向受保护手动账号缺失,先按账号所有权恢复或退役该手动账号,不把它混同为 YAML-managed pool 账号失败。
- pool key 401:跑 `codex-pool sync --confirm` 重建 Sub2API key 与 k3s Secret 绑定,再跑 `codex-pool validate`
- pool key、admin password 或 k8s Secret `.data` 被 stdout、日志、issue 或本地 transcript 打印时,按泄露处理:撤销对应 Sub2API key 或 token,删除/重建受影响的 target Secret,通过 `codex-pool sync --target <id> --confirm` 或相应 YAML sourceRef 重新下发,再用 fingerprint、presence 和 `valuesPrinted=false` 作为 closeout 证据;不要复述旧值或新值。
- 运行中过去的验证探针残留:只用 `codex-pool cleanup-probes --confirm` 清理 `unidesk-probe-*` 临时资源;不要把真实 managed account 删除当作探针清理或可用性恢复。
- default profile 递归:检查 YAML default entry 是否使用 `*.pre-sub2api` 备份文件;必要时恢复备份后重新 `configure-local --confirm`
- 上游需要 WebSocket v2:先做 direct Codex WSv2 probe;通过后才给该 profile 配 `openaiResponsesWebSocketsV2Mode: ctx_pool|passthrough` 并跑 `sync --confirm`;把它当 capability candidate,容量仍以 YAML 中的 `capacity` 或默认值为准。
- Codex 启动 WebSocket 回退:用原入口 Codex smoke 复现,再用 bounded Sub2API 日志确认 account;对 WS handshake 4xx/5xx、`openai.websocket_account_select_failed` 或 close-before-`response.completed` 的账号关闭 YAML WSv2 能力后同步。若没有剩余 WSv2-capable account,把 `localCodex.supportsWebSockets``localCodex.responsesWebSocketsV2` 一起关掉,不把临时可用性推断写成调度配置。
- 上游要求 Codex User-Agent:只给该 profile 配 `upstreamUserAgent`,跑 `sync --confirm`
- 上游报 capacity/rate-limit/overload/Bad Gateway/Gateway Timeout 后没有隔离或频繁先失败再恢复:先看 `codex-pool sentinel-report` 的 marker、动作、冻结 TTL 和下一次 probe,也看 `codex-pool validate --full` 的 recent gateway failover/forward failure 证据;同时对照当前 Sub2API 源码里 `/v1/responses` handler、`Forward``shouldFailoverOpenAIUpstreamResponse``handleOpenAIAccountUpstreamError` 的真实传播路径。不要手动禁用账号、删除账号、改 membership/priority/capacity/loadFactor 或从 YAML 移除问题账号来替代通用 failover 与哨兵隔离/恢复。
- Codex 报 weekly-limit、`less than 10% of your weekly limit left``Run /status for a breakdown` 等账号状态/软配额提示并要求切号:不要把新关键词写成 Sub2API 内置临时不可调度策略来恢复可用性;由 marker-only 哨兵按非 marker 响应统一冻结,并用 `sentinel-report` / `sentinel-probe` 验证。
- 上游 400/503 响应体出现 `invalid_encrypted_content``bad_response_status_code``invalid_request_error` + 稳定 unsupported-model 文案、unsupported-model、`暂不支持` / `可用模型``model_not_found``No available channel for model ...` 或同类稳定模型路由 / Responses encrypted-content 兼容性失败:按通用 temp-unschedulable/failover 加哨兵 marker 证据处理,不用 account membership、priority、capacity、loadFactor、WebSocket mode、User-Agent 或 provider pinning 掩盖该错误族。
- 上游错误反复触发:`invalid_encrypted_content`、unsupported-model、`Recovered upstream error ...``Bad Gateway``Gateway Timeout`、Cloudflare `524`、Codex-facing `Upstream request failed``Unknown error``context deadline exceeded``context canceled``model_not_found``No available channel for model`、大上下文 `413``openai_error` 这类稳定包装文案,先确认 YAML temp-unschedulable 已同步、Sub2API 源码会把该错误族传播成 `UpstreamFailoverError`、运行日志出现 `openai.upstream_failover_switching`。若匹配规则后仍只看到 `openai.forward_failed`,根因是 Sub2API HTTP `/responses` 没把该错误传播成 `UpstreamFailoverError`,应修 Sub2API failover classifier/error propagation,不硬编码账号或给 `only` 特权。
- Codex auto compact 后丢上下文:先确认 YAML `localCodex` 是否声明启用 WSv2;若启用,再确认本机 `~/.codex/config.toml` 是否有 `supports_websockets = true``responses_websockets_v2 = true`,并看 `codex-pool validate` 的 WSv2 candidate 和 Sub2API 日志里的 `transport=responses_websockets_v2`。若 YAML 当前禁用 WSv2,则按 HTTP Responses 稳定性排查,不把旧 WS 口径当成验收要求。
- Codex smoke 有 reconnect/1013:这是上游并发/可用性问题,和 HTTP-only compact context-loss 分开处理;记录 session/log 证据并关联专项 issue,不要用运行时手补覆盖 YAML 容量。