Troubleshooting (中文 (简体))
第一次使用 OmniRoute? 从这里开始——这些方法能解决 90% 的问题:
| 我看到的情况 | 含义 | 该怎么做 |
|---|---|---|
| “无法连接” | OmniRoute 未运行 | 运行 omniroute 或 docker restart omniroute |
| “API 密钥无效” | 你的密钥错误或已过期 | 从提供者网站重新复制密钥 |
| “超出速率限制” | 你发送了过多请求 | 等待 1 分钟,或使用 model: "auto" 自动回退 |
| “超出配额” | 你的免费/付费配额已用完 | 连接更多提供者,或使用免费提供者(Kiro、Pollinations) |
| “响应缓慢” | 提供者繁忙或距离较远 | 使用 model: "auto/fast",或连接速度更快的提供者(Groq、Cerebras) |
| “使用了错误的提供者” | auto 选择了其他提供者 |
这是正常现象!auto 会选择最佳提供者。使用 model: "openai/gpt-4o" 强制指定提供者 |
| “502 网关错误” | 提供者不可用 | 等待后重试,或使用 model: "auto" 切换提供者 |
| “401 未授权” | 你的凭据有误 | 检查 API 密钥,或使用 OAuth 重新进行身份验证 |
| “无法识别 omniroute” | Windows PATH 中缺少全局 node 模块 | 将 npm 全局前缀添加到 Windows PATH。使用 npm config get prefix 查找该前缀。 |
| “429 请求过多” | 受到速率限制 | 等待 1 分钟,或连接更多提供者 |
仍然无法解决? 请参阅下方的详细故障排除,或前往 Discord 提问。
详细故障排除
Section titled “详细故障排除”免费提供者的速率限制(429 / 400 / 401)
Section titled “免费提供者的速率限制(429 / 400 / 401)”症状:通过免费/无需身份验证的提供者(opencode、auggie 等)使用 model: "auto" 时,会间歇性收到 HTTP 429、400 或 401,而不是正常回答。稍后使用相同提示词重试时请求可以成功,但自动化任务(cron 作业、智能体、脚本)会在第一次失败时中断。
根本原因:三个相互独立的故障模式叠加在一起:
- 提供者速率限制(
429):免费套餐可能会针对每个时间窗口实施配额限制。大量并行调用会耗尽配额,因此在时间窗口重置之前,后续请求都会被拒绝。 - 直通模式中的失效模型(
400/401):auto/*池中可能包含来自opencode的直通模型,这些模型已在目录中注册,但没有有效凭据(例如oc/north-mini-code-free→401)。自动路由器尝试调用其中一个模型并失败,错误会在回退机制启动前向上传播。 - 并发放大效应(负载下出现
429):当多个智能体/cron 会话同时调用auto时,总请求速率会超过免费提供者的承受能力,导致正常调用被标记为滥用。
已验证的修复方案(社区报告,2026-08-10):调整三个环境变量,使轮换、并发控制和回退机制能够消化免费套餐的不稳定性,而不是因此直接失败:
export OMNIROUTE_ROTATE_ON_400=true # 遇到 400/401 时跳转到其他模型/提供者(跳过失效的直通模型)export OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT=4 # 明确设置重量级请求准入上限(默认未设置:不限制请求数量,参见下方说明)export OMNIROUTE_CHAT_ADMISSION_QUEUE_MS=5000 # 在等待重量级请求容量时采用更长但有上限的等待时间,而不是立即返回可重试的 503在 OmniRoute 进程环境中设置这些变量(即守护进程,例如通过 LaunchAgent plist 或 systemctl edit),然后重新启动 OmniRoute。轮换标志是效果最显著的单项设置:它可以将硬性失败转换为对池中健康提供者的透明重试。
注意:OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT 用于限制同时运行的重量级(即长上下文)请求数量;该限制是准入门控,而不是提供者速率限制器。**#503 扇出更新:**此变量默认不再设置(现在只有像上面那样显式配置时才会生效)——重量级请求准入将改由自动推导的字节预算(OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES)进行控制,该预算会根据主机的实际内存上限自动调整,因此全新部署即使完全不设置此变量,也应该会遇到明显更少的 503 chat_admission_busy 拒绝;在此处显式设置它仍会完全按照文档所述工作。显式字节预算覆盖值会被限制在 8 MiB–2 GiB 之间。413 body_exceeds_budget 并非暂时性错误:请提高该字节预算、降低 OMNIROUTE_CHAT_HARD_MAX_BODY_BYTES,或提高进程内存上限。inflight_bytes_budget 导致的请求卸载属于暂时性资源争用,仍可重试。每个提供者的速率限制(open-sse/services/rateLimitManager.ts)由 RATE_LIMIT_MAX_WAIT_MS、RATE_LIMIT_MAX_QUEUE_DEPTH 和 RATE_LIMIT_AUTO_ENABLE 单独控制——请参阅 .env.example。
如何验证修复是否生效:快速连续运行两次你的代理/cron,并确认两次都成功。修复前,第二次运行通常会抛出 429/401。修复后,失败(如果有)会自动重试,并最终完成调用。你也可以执行 curl /monitoring/health,观察提供者连接中的 rateLimitedUntil 字段,以及受影响提供者对应的 circuitBreakers.providerBreakers[].state——状态可能是 CLOSED、DEGRADED、OPEN 或 HALF_OPEN(参见 src/shared/utils/circuitBreaker.ts);持续失败的提供者会依次从 CLOSED → DEGRADED → OPEN 切换,之后重置窗口会允许一次探测请求通过(HALF_OPEN)。
如果仍然看到 429:该提供者的当前活跃账户确实已耗尽其_配额_(而不仅仅是触发速率限制)。请在 OmniRoute 控制面板中依次进入 Providers → Accounts,为同一提供者添加第二个账户;或者混合使用另一个免费提供者(例如 routeway、auggie)。轮换仅有助于处理暂时性的速率限制/400/401;如果配额已彻底耗尽,则需要第二组凭据或改用其他提供者。
如果在视觉模型(auto/vision、bazaarlink/*)上看到 403:已连接的账户没有包含视觉功能的付费套餐,或者 API 密钥权限不足。请在提供者控制面板中确认该密钥的权限范围包含视觉/多模态功能,或者连接一个付费层级账户,并将其继续用作视觉任务的目标账户。
npm install 警告(ERESOLVE / peer / deprecated)
Section titled “npm install 警告(ERESOLVE / peer / deprecated)”运行 npm install -g omniroute 时,你可能会看到大量警告,例如 npm warn ERESOLVE、对等依赖通知以及 deprecated 消息。这些是预期行为,不会造成影响。 如果输出中显示 added <N> packages,则表示安装已成功。
要抑制对等依赖解析警告,请使用 OmniRoute 支持的安装方式:
npm install -g omniroute --legacy-peer-deps--legacy-peer-deps 仅抑制 ERESOLVE 和对等依赖通知。弃用通知仍然可见,因为它们来自传递依赖的第三方软件包;这些通知并不表示安装失败。
这些警告来自 OmniRoute 无法控制的第三方软件包中过时的对等依赖版本范围:
marked-terminal要求marked >=1 <16,但检测到marked@18— 实际使用没有问题;只是上游的对等依赖版本范围已过时。deprecated prebuild-install@7.1.3— 一个传递依赖的原生二进制文件获取辅助工具。它并不 用于安装固定版本的wreq-js传输绑定,也不表示 Web Cookie 提供程序的传输设置失败。
无需采取任何操作 — 如果不 fork 上游软件包,就无法完全消除这些警告。
Gemini Web 和 Playwright Chromium
Section titled “Gemini Web 和 Playwright Chromium”如果 Gemini Web 请求返回 503,并显示 Playwright Chromium
尚未安装,则表示 npm 软件包已存在,但缺少浏览器二进制文件。
Playwright 有意将浏览器下载与 npm 软件包
安装分开,因此在安装浏览器之前出现此响应属于预期行为。
对于全局 npm 安装,请从 OmniRoute 软件包 目录安装 Chromium,以便浏览器缓存归属于同一个 Playwright 安装:
cd "$(npm root -g)/omniroute"npx playwright install chromium安装后重启 OmniRoute,然后重试 Gemini Web 请求。如果你
通过 Docker 镜像运行 OmniRoute,请使用 -web 镜像(或 runner-web
构建目标),其中已包含 Chromium 及其依赖项;基础镜像
不包含这些内容。
| 问题 | 解决方案 |
|---|---|
| 首次登录无法使用 | 在 .env 中设置 INITIAL_PASSWORD(没有硬编码的默认值) |
| 仪表板在错误的端口上打开 | 设置 PORT=20128 和 NEXT_PUBLIC_BASE_URL=http://localhost:20128 |
| 没有日志写入磁盘 | 设置 APP_LOG_TO_FILE=true,并确认已启用调用日志捕获 |
| EACCES:权限被拒绝 | 设置 DATA_DIR=/path/to/writable/dir 以覆盖 ~/.omniroute |
| 路由策略无法保存 | 更新到最新的 v3.x 版本(用于设置持久化的 Zod 模式修复已在较早版本中发布) |
| 登录崩溃/页面空白 | 检查 Node.js 版本 — 请参阅下方的 Node.js 兼容性 |
dlopen / slice is not valid mach-o file(macOS) |
运行 cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute — 请参阅下方的 macOS 原生模块重新构建 |
| 代理出现“fetch failed” | 确保在正确的层级设置代理配置 — 请参阅下方的 代理问题 |
Docker curl: (56) Recv failure: Connection reset by peer |
Docker 端口绑定可能落在 IPv6 上。使用 -p 127.0.0.1:20128:20128 强制使用 IPv4,或使用 curl -4 进行测试。请参阅下方的 Docker IPv6 |
杀毒软件隔离 README.md |
误报 — 请参阅下方的 杀毒软件误报 |
| Kaspersky 将桌面应用标记为木马 | 对未签名安装程序的行为误报 — 请参阅下方的 杀毒软件误报 |
杀毒软件误报
Section titled “杀毒软件误报”Avast/AVG 以 MD:HttpRequest-inf[Susp] 为由隔离 README.md
Section titled “Avast/AVG 以 MD:HttpRequest-inf[Susp] 为由隔离 README.md”这是误报。没有任何内容受到感染,也无需采取任何操作。
Avast 和 AVG 会运行一种启发式检测,将包含大量疑似 HTTP 请求链接的纯文本/Markdown 文件标记为可疑。OmniRoute 的 README.md 随 npm 包一起分发(它列在 package.json → files 中),因此在全局安装时会出现在 node_modules/omniroute/README.md;而且该文件包含约 15 个 http://localhost:20128/... 示例(MCP HTTP/SSE 端点、A2A .well-known URL 和 curl 代码片段)。如此高的链接密度足以触发该启发式检测。
如果这种情况只是最近才开始出现:文件的性质并没有改变。README 扩充了端点表(新增了 MCP HTTP + SSE + A2A)以及更多 curl 示例,因而超过了检测阈值。
该文件只是静态文档,不包含任何可执行内容。你可以放心地从隔离区恢复它。
处理方法:
- 停止通知 — 在杀毒软件中排除安装目录(Avast:设置 → 例外),添加你的全局
node_modules路径和/或 OmniRoute 数据目录(~/.omniroute/)。 - 报告误报 — https://www.avast.com/false-positive-file-form.php,并附上被隔离的
README.md。这才是能帮助所有人的解决方式,因为问题在于厂商的启发式检测对文本文件反应过度。
**为什么我们不在自身这一侧“修复”它:**所有示例都使用 http://localhost,而 localhost 若不引入自签名证书带来的麻烦,就无法使用 https。为了规避某一家厂商的启发式检测而篡改文档,会损害所有读者的使用体验,仅仅为了迁就一个扫描器缺陷。
Kaspersky 将桌面应用标记为 PDM:Trojan.Win32.Generic
Section titled “Kaspersky 将桌面应用标记为 PDM:Trojan.Win32.Generic”这是行为启发式检测造成的误报。没有任何内容受到感染。 Kaspersky 的 PDM: 前缀表示该判定来自其主动防御模块(系统监控),它会判断安装程序执行的_行为_,而不是将其与已知恶意软件进行匹配。触发检测时,Kaspersky 会“回滚”整个安装过程——删除它已经写入的文件——因此应用最终会损坏或消失。
它所标记的文件是桌面应用中已声明的开源依赖项的标准组成部分,例如:
resources/app/.build/next/node_modules/playwright-<hash>/lib/…/agentParser.js和workerProcessEntry.js— Playwright,用于应用内提供者登录和浏览器支持聊天的浏览器自动化库。resources/app/.build/next/node_modules/@wreq-js/binding-win32-<arch>-msvc-<hash>/wreq-js.win32-<arch>-msvc.node— 固定版本的wreq-js原生绑定,用于在依赖 Web Cookie 的提供者上实现具有浏览器指纹特征的 HTTP(<arch>为x64或arm64)。
触发原因:Windows 安装程序尚未进行代码签名,因此未签名的 NSIS 安装程序没有任何信誉记录,行为启发式检测会以最高强度运行。再加上安装包中包含原生 DLL,并会在 %LOCALAPPDATA%\Programs\OmniRoute 下写入数百个 .js 文件(包括 Next.js 独立构建生成的带哈希后缀的包目录),这些因素足以触发该启发式检测。代码签名已列入计划;在实施之前,新版本仍可能重复出现此问题。
处理方法:
- 首先验证下载文件(以排除文件被篡改的可能)。每个版本都会发布
latest.yml,其中的sha512字段(base64)涵盖OmniRoute.Setup.<version>.exe安装程序。在 PowerShell 中,从包含安装程序的文件夹运行:输出必须与终端窗口 $b = [System.Security.Cryptography.SHA512]::Create().ComputeHash([System.IO.File]::ReadAllBytes("$PWD\OmniRoute.Setup.<version>.exe"))[Convert]::ToBase64String($b)latest.yml→sha512匹配。如果不匹配,请删除该文件,并仅从 GitHub 发布页面重新下载。 - 恢复并排除 — 从隔离区恢复被回滚的项目,并为
%LOCALAPPDATA%\Programs\OmniRoute添加排除项(Kaspersky → 设置 → 威胁和排除项),然后重新安装。 - 报告误报 — https://opentip.kaspersky.com/。用户提交的误报报告确实有助于加快加入允许列表的速度。
Node.js 兼容性
Section titled “Node.js 兼容性”登录页面崩溃或显示“Module self-registration”错误
Section titled “登录页面崩溃或显示“Module self-registration”错误”原因: 您正在运行的 Node.js 版本不符合 OmniRoute 批准的最低安全运行时要求。最常见的情况是,所运行的 Node 22 或 24 补丁版本低于 OmniRoute 要求的已修复安全版本下限。
症状:
- 登录页面显示空白屏幕或服务器错误
- 控制台显示
Error: Module did not self-register或类似的原生绑定错误 - 如果运行时不符合受支持的安全策略,登录页面会显示一个包含您的 Node 版本的橙色警告横幅
修复方法:
- 安装受支持的 Node.js LTS 版本(推荐:Node.js 24.x):
终端窗口 nvm install 24nvm use 24 - 验证您的版本:
node --version应显示 24.x LTS 系列中的v24.0.0或更高版本 - 重新安装 OmniRoute:
npm install -g omniroute - 重新启动:
omniroute
受支持的安全版本:
>=22.22.2 <23或>=24.0.0 <27。完全支持 Node.js 24.x LTS (Krypton) 和 Node.js 26。
npm v11+:未安装 better-sqlite3(Cannot find module)
Section titled “npm v11+:未安装 better-sqlite3(Cannot find module)”原因: npm v11(随 Node.js 24+ 提供)默认会阻止可选依赖项的安装脚本。由于 better-sqlite3 列在 optionalDependencies 中,并且需要进行原生编译(node-gyp rebuild),因此 npm 会静默跳过它。
症状:
- 服务器启动时崩溃并显示
Cannot find module 'better-sqlite3' ls node_modules/better-sqlite3显示“No such file or directory”npm ls better-sqlite3显示(empty)
修复方法:
- 批准安装脚本并重新安装:
终端窗口 npm approve-scripts better-sqlite3npm install - 或手动安装预构建版本:
终端窗口 npm pack better-sqlite3@13.0.1tar -xzf better-sqlite3-*.tgz -C node_modulesmv node_modules/package node_modules/better-sqlite3rm better-sqlite3-*.tgz - 验证其是否正常工作:
node -e "require('better-sqlite3')(':memory:').close(); console.log('OK')"
macOS:dlopen / “slice is not valid mach-o file”
Section titled “macOS:dlopen / “slice is not valid mach-o file””原因: 全局执行 npm install -g omniroute 后,软件包内的 better-sqlite3 原生二进制文件可能是针对与本地运行环境不同的架构或 Node.js ABI 编译的。当预构建二进制文件与您的环境不匹配时,这种情况在 macOS(包括 Apple Silicon 和 Intel)上很常见。
症状:
- 服务器启动时立即失败,并显示
dlopen错误 - 错误中包含
slice is not valid mach-o file - 完整示例:
dlopen(/Users/<user>/.nvm/versions/node/v24.14.1/lib/node_modules/omniroute/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node, 0x0001): tried: '...' (slice is not valid mach-o file)修复方法——针对您的本地环境重新构建(无需降级 Node.js):
cd $(npm root -g)/omniroute/appnpm rebuild better-sqlite3omniroute注意: 这会针对您的本地 Node.js 版本和 CPU 架构重新编译原生绑定,从而解决二进制文件不匹配问题。官方支持的运行时范围为
>=22.22.2 <23或>=24.0.0 <27(位于src/shared/utils/nodeRuntimeSupport.ts中的SUPPORTED_NODE_RANGE,与package.json的engines字段保持一致)。完全支持将 Node.js 24.x LTS (Krypton) 和 Node.js 26 与better-sqlite3v12.x 搭配使用。
提供者验证显示 “fetch failed”
Section titled “提供者验证显示 “fetch failed””原因: API 密钥验证端点 (POST /api/providers/validate) 之前会绕过代理配置,导致在需要通过代理路由的环境中验证失败。
修复 (v3.5.5+): 此问题现已修复。提供者验证现在通过 runWithProxyContext 路由,并自动遵循提供者级别和全局代理设置。
令牌健康检查因 “fetch failed” 而失败
Section titled “令牌健康检查因 “fetch failed” 而失败”原因: 后台 OAuth 令牌刷新未按连接解析代理配置。
修复 (v3.5.5+): 令牌健康检查调度器现在会在尝试刷新前按连接解析代理配置。请更新到 v3.5.5+。
SOCKS5 代理返回 “invalid onRequestStart method”
Section titled “SOCKS5 代理返回 “invalid onRequestStart method””原因: 在 Node.js 22 上,undici@8 调度器与 Node 内置的 fetch() 实现不兼容。
修复 (v3.5.5+): 现在,当代理调度器处于活动状态时,OmniRoute 会使用 undici 自身的 fetch() 函数,以确保行为一致。请更新到 v3.5.5+。
WSL 下的 MITM 代理:Windows 主机上的桌面应用未被拦截
Section titled “WSL 下的 MITM 代理:Windows 主机上的桌面应用未被拦截”原因: MITM 代理及其 CA 证书会安装到 OmniRoute 运行所在的环境中。在 WSL 下,该环境是 Linux 客户机,而 AI 桌面应用(Kiro、Trae、Copilot、Zed 等)运行在 Windows 主机上。主机应用不信任客户机的证书存储,也不会通过客户机的系统代理进行路由,因此无法对桌面应用启用拦截。
建议: 在与要拦截的桌面应用相同的操作系统上原生运行 OmniRoute(Windows 应用在 Windows 上运行;macOS/Linux 同理)。如果将 OmniRoute 保留在 WSL 内,同时以主机应用为目标,则需要在 Windows 主机上手动信任生成的 CA 证书,并将每个主机应用的网络/代理设置指向 WSL 代理端点——这种配置不受支持且非常脆弱。
“Language model did not provide messages”
Section titled ““Language model did not provide messages””原因: 提供者配额已用尽。
修复:
- 检查仪表板中的配额跟踪器
- 使用带有回退层级的组合
- 切换到更便宜的层级或免费层级
原因: 订阅配额已用尽。
修复:
- 添加回退:
cc/claude-opus-4-6 → glm/glm-4.7 → if/qwen3.8-max-preview - 使用 GLM/MiniMax 作为低成本备用方案
OAuth 令牌已过期
Section titled “OAuth 令牌已过期”OmniRoute 会自动刷新令牌。如果问题仍然存在:
- 仪表板 → 提供者 → 重新连接
- 删除并重新添加提供者连接
Kiro 多账户:第二个账户会使第一个账户失效
Section titled “Kiro 多账户:第二个账户会使第一个账户失效”原因: Kiro 的后端强制要求每个 OIDC 客户端注册只能有一个活动会话。 当两个账户共享同一个已注册的客户端(即在 v3.8.0 之前导入的连接)时, 刷新其中一个账户的令牌会使另一个账户的刷新令牌失效。
修复 (v3.8.0+): 重新导入受影响的连接。 从 v3.8.0 开始,通过导入令牌、 Google/GitHub 社交登录或自动导入创建的每个新 Kiro 连接都会自动注册其自己 专用的 OIDC 客户端。因此,该连接将完全隔离,刷新一个 账户不会对任何其他账户产生影响。
在 v3.8.0 之前 导入的连接没有按连接分配的客户端 注册。这些连接会继续使用共享的社交身份验证刷新端点。 要实现隔离,请从仪表板 → 提供者中删除旧连接,然后通过 上述三种导入流程中的任意一种重新添加。
有关完整详情以及并行添加两个 Kiro 账户的分步说明,
请参阅 docs/guides/KIRO_SETUP.md。
- 确认
BASE_URL指向正在运行的实例(例如http://localhost:20128) - 确认
CLOUD_URL指向云端端点(例如https://omniroute.dev) - 保持
NEXT_PUBLIC_*的值与服务端的值一致
云端 stream=false 返回 500
Section titled “云端 stream=false 返回 500”症状: 在云端端点进行非流式调用时出现 Unexpected token 'd'...。
原因: 上游返回 SSE 负载,而客户端期望接收 JSON。
解决方法: 云端直连调用请使用 stream=true。本地运行时包含 SSE→JSON 回退机制。
云端显示已连接,但提示“Invalid API key”
Section titled “云端显示已连接,但提示“Invalid API key””- 从本地仪表板创建新密钥(
/api/keys) - 执行云同步:启用云端 → 立即同步
- 旧密钥或未同步的密钥在云端仍可能返回
401
Docker 问题
Section titled “Docker 问题”Docker IPv6 / 连接重置
Section titled “Docker IPv6 / 连接重置”症状: curl http://localhost:20128/v1/models 返回 curl: (56) Recv failure: Connection reset by peer。仪表板和未认证的端点可以正常工作,但已认证的端点会失败——这看起来像认证问题,但实际上并非如此。
原因: docker run -p 20128:20128 会同时发布到 0.0.0.0(IPv4)和 ::(IPv6),但容器内的进程仅监听 IPv4。在 localhost 优先解析为 ::1 的主机上,连接会到达已发布的 IPv6 端口,但其后端没有监听器 → 连接被重置。
修复方法:
- 快速诊断: 运行
curl -4 http://localhost:20128/v1/models。如果添加-4后可以正常工作,而不添加时失败,则存在 IPv6 绑定不匹配问题。 - 永久修复: 在
docker run命令中使用-p 127.0.0.1:20128:20128,显式绑定到 IPv4:这会强制绑定到 IPv4,同时避免将代理暴露在主机的所有网络接口上。终端窗口 docker run -d --name omniroute --restart unless-stopped --stop-timeout 40 \-p 127.0.0.1:20128:20128 -v omniroute-data:/app/data diegosouzapw/omniroute:latest
CLI 工具显示未安装
Section titled “CLI 工具显示未安装”- 检查运行时字段:
curl http://localhost:20128/api/cli-tools/runtime/codex | jq - 对于便携模式:使用镜像目标
runner-cli(内置 CLI) - 对于主机挂载模式:设置
CLI_EXTRA_PATHS,并以只读方式挂载主机的二进制文件目录 - 如果
installed=true且runnable=false:已找到二进制文件,但健康检查失败
快速验证运行时
Section titled “快速验证运行时”curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'- 在仪表板 → 用量中查看使用统计信息
- 将主模型切换为 GLM/MiniMax
- 对非关键任务使用免费套餐(Qoder、Kiro)
- 为每个 API 密钥设置成本预算:仪表板 → API 密钥 → 预算
启用日志文件
Section titled “启用日志文件”在 .env 文件中设置 APP_LOG_TO_FILE=true。应用程序日志会写入 logs/。
在设置中启用调用日志管道后,请求产物会存储在 ${DATA_DIR}/call_logs/ 下。
启用管道捕获后,可设置 CALL_LOG_PIPELINE_CAPTURE_STREAM_CHUNKS=false 以省略
流数据块负载,或调整 CALL_LOG_PIPELINE_MAX_SIZE_KB 以更改以 KB 为单位的产物大小上限。
检查提供者健康状态
Section titled “检查提供者健康状态”# 健康状态仪表板http://localhost:20128/dashboard/health
# API 健康检查curl http://localhost:20128/api/monitoring/health- 主要状态:
${DATA_DIR}/storage.sqlite(提供者、组合、别名、密钥、设置) - 用量:
storage.sqlite中的 SQLite 表(usage_history、call_logs、proxy_logs)+ 可选的${DATA_DIR}/call_logs/ - 应用程序日志:
<repo>/logs/...(当APP_LOG_TO_FILE=true时) - 调用日志产物:启用调用日志管道后,存储于
${DATA_DIR}/call_logs/YYYY-MM-DD/...
请求日志页面中的清理历史记录操作会清除 call_logs、旧版
request_detail_logs,以及本地 ${DATA_DIR}/call_logs/ 产物目录。
提供者卡在 OPEN 状态
Section titled “提供者卡在 OPEN 状态”当提供者的熔断器处于 OPEN 状态时,请求将被阻止,直到冷却时间结束。
解决方法:
- 前往 控制面板 → 设置 → 弹性
- 查看受影响提供者的熔断器卡片
- 点击 全部重置 以清除所有熔断器,或等待冷却时间结束
- 重置前,请确认提供者确实可用
提供者持续触发熔断器
Section titled “提供者持续触发熔断器”如果提供者反复进入 OPEN 状态:
- 在 控制面板 → 健康状态 → 提供者健康状态 中检查故障模式
- 前往 设置 → 弹性 → 提供者配置文件,并提高故障阈值
- 检查提供者是否更改了 API 限制,或者是否需要重新进行身份验证
- 检查延迟遥测数据——高延迟可能会导致基于超时的故障
音频转录问题
Section titled “音频转录问题”“不支持的模型”错误
Section titled ““不支持的模型”错误”- 使用第一段为您已配置凭据的提供者的模型 ID(
openai/whisper-1、openrouter/deepgram/nova-3)。直接使用deepgram/nova-3需要原生 Deepgram 密钥。 - 确认提供者已在 控制面板 → 提供者 中连接
转录结果为空或转录失败
Section titled “转录结果为空或转录失败”- 检查支持的音频格式:
mp3、wav、m4a、flac、ogg、webm - 确认文件大小未超过提供者限制(通常 < 25MB)
- 在提供者卡片中检查提供者 API 密钥是否有效
使用 控制面板 → 翻译器 调试格式转换问题:
| 模式 | 使用场景 |
|---|---|
| 演练场 | 并排比较输入/输出格式——粘贴失败的请求以查看其转换结果 |
| 聊天测试器 | 发送实时消息,并检查包含标头在内的完整请求/响应载荷 |
| 测试台 | 对多种格式组合运行批量测试,以找出发生故障的转换 |
| 实时监控器 | 观察实时请求流,以捕获间歇性转换问题 |
常见格式问题
Section titled “常见格式问题”- 未显示思考标签——检查目标提供者是否支持思考功能以及思考预算设置
- 工具调用丢失——某些格式转换可能会去除不支持的字段;请在演练场模式下进行验证
- 缺少系统提示词——Claude 和 Gemini 处理系统提示词的方式不同;请检查转换输出
- SDK 返回原始字符串而非对象——已在 v1.x 中解决;响应清理器会去除导致 OpenAI SDK Pydantic 验证失败的非标准字段(
x_groq、usage_breakdown等)。如果您在 v3.x+ 中仍遇到此问题,请提交 issue。 - GLM/ERNIE 拒绝
system角色——已在 v1.x 中解决;角色规范化器会自动将系统消息合并到用户消息中,以适配不兼容的模型。如果您在 v3.x+ 中仍遇到此问题,请提交 issue。 - 无法识别
developer角色——已在 v1.x 中解决;对于非 OpenAI 提供者,会自动将其转换为system。如果您在 v3.x+ 中仍遇到此问题,请提交 issue。 json_schema无法与 Gemini 配合使用——已在 v1.x 中解决;现在会将response_format转换为 Gemini 的responseMimeType+responseSchema。如果您在 v3.x+ 中仍遇到此问题,请提交 issue。
自动速率限制未触发
Section titled “自动速率限制未触发”- 自动速率限制仅适用于 API 密钥提供者(不适用于 OAuth/订阅)
- 验证 设置 → 弹性 → 提供者配置文件 是否已启用自动速率限制
- 检查提供者是否返回
429状态码或Retry-After标头
调整指数退避
Section titled “调整指数退避”提供者配置文件支持以下设置:
- 基础延迟 — 首次失败后的初始等待时间(默认值:1s)
- 最大延迟 — 最长等待时间上限(默认值:30s)
- 乘数 — 每次连续失败后延迟增加的倍数(默认值:2x)
防止惊群效应
Section titled “防止惊群效应”当大量并发请求访问受到速率限制的提供者时,OmniRoute 会使用互斥锁 + 自动速率限制来串行化请求并防止级联故障。对于 API 密钥提供者,此机制会自动启用。
聊天请求失败并返回 503 / chat_admission_busy
Section titled “聊天请求失败并返回 503 / chat_admission_busy”症状:
- 聊天补全端点返回可重试的
503响应,其错误代码为chat_admission_busy。 - 响应包含
Retry-After。自 #12135 起,该值根据观测到的 占用情况计算得出——取请求已经等待的OMNIROUTE_CHAT_ADMISSION_QUEUE_MS窗口 与当前重量级租约已持有时间中的较大值——向上舍入到整秒, 并以 60 秒为上限。在空闲准入门控上,它会保留历史下限:基于字节的路径为 2 秒, 基于结构的路径为 1 秒(后者还会包含reason: "structure_limit")。 - 当另一个重量级聊天请求或长时间运行的流式响应仍在 处理中时,可能会发生这种情况。
基于字节的响应正文为:
{ "error": { "message": "Chat admission capacity is temporarily unavailable. Retry shortly.", "type": "server_error", "code": "chat_admission_busy" }}基于结构的响应使用相同的类型和代码,其消息为
Local chat admission capacity is busy for this structurally heavy request; upstream provider routing was not attempted. Retry shortly.
并包含 reason: "structure_limit"。
在默认阈值下,如果请求包含至少 200 条消息、
至少 64 个工具或至少 32,000 个估算令牌,或者有界结构估算
耗尽了 10,000 个已访问节点或深度 12 的限制,则该请求会被视为结构重量级请求。
原因: 这是 OmniRoute 内部有意执行的负载卸除,而不是上游提供者故障。 每个进程都会使用进程本地守卫,在保留并解析大型请求正文之前预留有限的 重量级容量。重量级租约会在 SSE 响应的整个生命周期内保持占用。
#503 扇出: 在此修复之前,无论主机内存如何,守卫都会将并发限制为固定的请求数量
(OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT,默认值为 1),因此编码代理的
扇出(多个子代理/CLI,请求正文通常 > 256 KB)会使有效并发量骤降至约 1,
并在完全正常的负载下返回 503。现在,守卫会进行自我调优:它由自动推导的
摄取字节预算(OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES)控制,该预算根据进程的
实际内存上限确定;同时还会参考实时资源压力信号——因此,它只会在主机确实
面临内存压力时卸除负载,而不会仅仅因为同时到达多个重量级请求就这样做。
旧的计数上限(OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT)仍然有效,但仅在你显式设置它时生效。
当容量繁忙时,重量级请求会先等待最多
OMNIROUTE_CHAT_ADMISSION_QUEUE_MS(默认值为 2000,设置为 0 将禁用等待),以便等待空位释放,
然后才返回可重试的 503。这种有界等待机制可让扇出并发重量级子请求的代理类客户端
(OpenCode、Claude Code、Cursor)将突发请求串行化,
而不是因立即遭到拒绝而耗尽全部重试预算并在任务中途终止。
当前重量级租约占用情况、解析后的字节预算和实时压力严重程度可在
GET /api/monitoring/health → chatAdmission(inflightBytes、maxInflightBytes、
budgetSource、pressureSeverity、countCapEnabled)中查看——在修改任何环境变量之前,请先检查这些值。
设置 → 弹性 → 请求队列 → 并发请求并不控制此机制;该设置
控制的是另一个独立的提供者请求队列机制。
修复方法:
- 首先重试。客户端应遵循
Retry-After并使用退避,而不是立即 重复请求。 - 在调整任何设置之前,请检查
/api/monitoring/health→chatAdmission。countCapEnabled: false且maxInflightBytes足够大,意味着自动推导的预算已经在正常 工作;如果pressureSeverity为high/critical,则表示主机确实内存不足—— 这种情况无法通过准入环境变量修复,需要增加 RAM 或减少工作负载。 - 仅当
/api/monitoring/health显示自动推导的预算对于你的 主机确实过小(这种情况很少见——它已经可以从容器扩展到裸机)时,才应直接使用OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES覆盖该预算,而不是退回使用旧版请求数量上限。
有关权威的准入设置,请参阅环境变量参考。
可选的 RAG / LLM 故障分类(16 个问题)
Section titled “可选的 RAG / LLM 故障分类(16 个问题)”一些 OmniRoute 用户会将网关部署在 RAG 或智能体技术栈之前。在这类配置中,经常会出现一种奇怪的情况:OmniRoute 看起来运行正常(提供者在线、路由配置正常、没有速率限制警报),但最终答案仍然是错误的。
实际上,这类事件通常源于下游 RAG 流水线,而不是网关本身。
如果你希望使用一套共同术语来描述这些故障,可以采用 WFGY ProblemMap。这是一个采用 MIT 许可证的外部文本资源,定义了十六种反复出现的 RAG / LLM 故障模式。总体而言,它涵盖:
- 检索漂移和上下文边界破坏
- 空索引或过期索引以及向量存储问题
- 嵌入与语义不匹配
- 提示词组装和上下文窗口问题
- 逻辑崩溃和过度自信的回答
- 长链路和智能体协调故障
- 多智能体记忆和角色漂移
- 部署和引导启动顺序问题
使用方法很简单:
- 调查错误响应时,记录:
- 用户任务和请求
- OmniRoute 中的路由或提供者组合
- 下游使用的所有 RAG 上下文(检索到的文档、工具调用等)
- 将事件映射到一个或两个 WFGY ProblemMap 编号(
No.1…No.16)。 - 在你自己的仪表板、运行手册或事件跟踪器中,将该编号记录在 OmniRoute 日志旁边。
- 使用对应的 WFGY 页面来判断是否需要更改 RAG 技术栈、检索器或路由策略。
完整文本和具体方案请参阅此处(MIT 许可证,纯文本):
如果你没有在 OmniRoute 后运行 RAG 或智能体流水线,可以忽略本节。
v3.8.0 已知问题
Section titled “v3.8.0 已知问题”以下是 v3.8.0 版本特有的问题及其当前解决方法。如果后续补丁中包含修复,此条目将被更新或删除。
Devin CLI 身份验证失败
Section titled “Devin CLI 身份验证失败”症状:
- 调用由 Devin 支持的工具时出现“Devin CLI not found”或“auth failed”
- CLI 运行时检查报告
installed=false
原因:
CLI_DEVIN_BIN指向不存在的路径- 主机上未安装 Devin CLI
解决方法:
- 安装适用于你平台的 Devin CLI
- 在
.env中设置CLI_DEVIN_BIN=/usr/local/bin/devin(或实际路径) - 重启 OmniRoute,然后从仪表板 → CLI 工具重新测试
模型冷却状态卡住(手动重置)
Section titled “模型冷却状态卡住(手动重置)”症状:
- 即使过期时间已过,模型仍显示为处于冷却状态
- 尽管时间戳已是过去时间,组合路由中的请求仍会跳过该模型
手动重置:
- 仪表板:设置 → 模型冷却 → 在受影响的卡片上点击重新启用
- **API:**使用管理身份验证请求头调用
DELETE /api/resilience/model-cooldowns
Command Code 提供者连接失败并返回 403
Section titled “Command Code 提供者连接失败并返回 403”症状:
- 测试 Command Code 提供者连接时返回 403
- 刚添加后,提供者卡片显示“unauthorized”
**原因:**OAuth 流程未完成(未收到回调或令牌未持久保存)。
解决方法:
- 从 CLI 运行
omniroute providers以重新触发 OAuth 流程,或者 - 从仪表板 → 提供者 → Command Code → 重新连接重新运行 OAuth
ModelScope 返回过于激进的 429 冷却
Section titled “ModelScope 返回过于激进的 429 冷却”症状:
- 在少量突发请求后,ModelScope 出现非常短或立即触发的冷却
- 组合路由比预期更早跳过 ModelScope
**原因:**ModelScope 会发出提供者特有的 Retry-After 请求头。v3.8.0 对这些请求头提供了专门处理,因此旧版本会将其错误地解读为通用的速率限制提示。
解决方法:
- 确保你使用的是 v3.8.0 或更高版本
- 验证设置 → 弹性机制下的
useUpstream429BreakerHints开关已启用
生产环境中缺少 OMNIROUTE_WS_BRIDGE_SECRET
Section titled “生产环境中缺少 OMNIROUTE_WS_BRIDGE_SECRET”症状:
- 在远程生产主机上运行时,每个 Codex/Responses WebSocket 桥接请求都返回 401
- WebSocket 桥接握手在连接后立即关闭
**原因:**生产环境中缺少 OMNIROUTE_WS_BRIDGE_SECRET 环境变量。
解决方法:
- 生成一个随机密钥:
openssl rand -hex 32 - 在生产服务器环境中设置
OMNIROUTE_WS_BRIDGE_SECRET=<random-secret>(以及在与该桥接通信的所有客户端中设置) - 重启 OmniRoute
Responses API:后台模式降级为同步模式
Section titled “Responses API:后台模式降级为同步模式”症状:
- 日志中记录警告:
background mode degraded to synchronous background: true请求返回普通同步响应,而不是后台作业句柄
**原因:**在 v3.8.0 中,Responses API 上的 background: true 会被有意降级为同步执行,同时发出警告。完整的异步后台执行功能将在未来交付。
解决方法:
- 调整客户端,使其调用时不使用
background,或者 - 等待提供完整异步后台模式的后续版本(请关注变更日志)
启动缓慢 / 就绪超时
Section titled “启动缓慢 / 就绪超时”如果 CLI 输出 ⚠ Server did not respond within 60s,但服务器实际上正常运行,则说明就绪探测的超时预算对于你的环境而言过短。
这种情况常见于 Windows(受杀毒软件、文件系统监视器影响)或启动工作负载较重的容器。
解决方法 — 增加超时预算:
# 通过环境变量设置(在多次启动之间保持有效):export OMNIROUTE_READY_TIMEOUT_MS=180000 # 3 分钟omniroute serve
# 通过 CLI 标志设置(仅本次有效):omniroute serve --ready-timeout 180000默认值为 60 000 ms(60 s)。该警告仅供参考;服务器会继续在后台启动,并在启动完成后可供访问。
有关 OMNIROUTE_READY_TIMEOUT_MS 的完整详情,请参阅 docs/reference/ENVIRONMENT.md。
仍然无法解决?
Section titled “仍然无法解决?”- GitHub Issues:github.com/diegosouzapw/OmniRoute/issues
- 架构:有关内部实现的详细信息,请参阅
docs/architecture/ARCHITECTURE.md - API 参考:有关所有端点的信息,请参阅
docs/reference/API_REFERENCE.md - 健康状态面板:前往 Dashboard → Health 查看实时系统状态
- 转换器:使用 Dashboard → Translator 调试格式问题
HagiCode
HagiCode 是一套智能体编码工作台:结构化工作流、多 Agent 并行执行与 Hero Dungeon 视图,把想法变成真正交付的软件。
让想法更快变成好用的软件,让智能编码更聪明、更高效,也更有趣。

- Smart结构化工作流将意图转化为从想法到交付的可执行路径。
- Efficient多 Agent 工作流让调研、实现与审阅并行推进。
- FunHero Dungeon 让长时间编码协作更直观、更有参与感。