[Bug] Dashboard 保存后无法通过重启生效 / Dashboard-saved config does not take effect after restart
中文
问题描述
在 Docker 容器中部署(非 systemd 托管),通过 Dashboard 管理模型时遇到两个连锁问题,导致模型启用后无法生效:
现象 1:Dashboard 上保存配置(带上了正确的 authorization: Bearer <BRIDGE_API_KEY>)能成功,保存后提示“需要重启”。
现象 2:点击「重启 Bridge」按钮时,请求没有携带 authorization 头,返回 401 Unauthorized。
现象 3:手动在浏览器/curl 中带上正确的 authorization: Bearer <key> 重新调用 POST /admin/restart,返回 {"ok":true},但容器进程实际没有重启(启动时间不变),因此配置没有重新加载,已启用(enabled:true)的模型始终不生效。
复现步骤
- 在
.env 设置 BRIDGE_API_KEY=sk-xxx(带 sk- 前缀)
- Docker 启动 Bridge,从
http://<IP>:9992 访问 Dashboard
- 在 Dashboard 开启某个模型(如
deepseek/deepseek-v4.1-flash)
- 点击「JSON 保存」→ 成功,提示重启
- 点击「重启 Bridge」→ 401 Unauthorized
- 用 curl 手动带对 key 调
POST /admin/restart → 返回 ok,但容器进程未重启,模型仍未启用
根本原因分析
问题 A:auth() 函数未使用 pendingBridgeKey(src/dashboard.ts)
function auth(){
const key = currentBridgeAuthKey() || (!pendingBridgeKey ? fullBridgeKey() : '') || '';
return key ? {'authorization':'Bearer '+key,...} : {'content-type':'application/json'}
}
- 当用户通过「💾/🎲」设置过 key 后,
pendingBridgeKey 变为真值
- 此时
currentBridgeAuthKey()(localStorage 无 key + 服务端返回 [REDACTED])返回空
- 且
pendingBridgeKey 为真时,!pendingBridgeKey 为 false,fullBridgeKey() 不会被调用
- 于是
auth() 返回不携带 Authorization 头的 headers → 服务端 401
抓包证据:保存请求(成功)带 authorization 头;但紧接着的重启请求(来自同一操作流)没有 authorization 头。原因是保存成功后 render()→syncBridgeKey() 把「客户端 API Key」输入框清空,且 pendingBridgeKey 处于异常状态。
建议修复:
const key = currentBridgeAuthKey() || pendingBridgeKey || fullBridgeKey() || '';
问题 B:Docker 非 systemd 下 restartBridge() 是 no-op(src/server.ts)
function restartBridge(): void {
if (process.platform === "linux") {
const supervisedBySystemd = Boolean(process.env.INVOCATION_ID || process.env.SYSTEMD_EXEC_PID);
if (supervisedBySystemd || process.env.COMMANDCODE_BRIDGE_RESTART_MODE === "exit") {
setTimeout(() => process.exit(0), 100).unref?.();
}
return; // ← Docker 非 systemd 且未设 COMMANDCODE_BRIDGE_RESTART_MODE 时,直接 return,什么都不做
}
// macOS launchctl 逻辑
}
在 Docker 容器(非 systemd)中,如果既没有 INVOCATION_ID/SYSTEMD_EXEC_PID,也没设置 COMMANDCODE_BRIDGE_RESTART_MODE=exit,restartBridge() 什么都不做。POST /admin/restart 返回 {"ok":true},但进程没退出、容器没重启、运行中的配置没重新加载 → 保存的模型启用不生效。
这需要在 Docker 部署文档中明确说明(如设置 restart: unless-stopped + COMMANDCODE_BRIDGE_RESTART_MODE=exit,或手动 docker restart)。
建议
- 修复
auth() 函数,让 pendingBridgeKey 也参与认证
- 在 Docker 部署文档中补充
restartBridge() 的生效前提(systemd 或 COMMANDCODE_BRIDGE_RESTART_MODE=exit + 容器 auto-restart)
环境
- 版本:1.53.0.a
- 部署:Docker 容器(非 systemd)
- 访问:
http://192.168.124.3:9992
- BRIDGE_API_KEY:以
sk- 开头
English
Description
Deployed in a Docker container (not managed by systemd). When managing models through the Dashboard, two cascading issues occur, causing enabled models to remain ineffective:
Symptom 1: Saving the configuration in the Dashboard (with the correct authorization: Bearer <BRIDGE_API_KEY>) succeeds, and after saving it prompts “restart required”.
Symptom 2: When clicking the “Restart Bridge” button, the request does not include the authorization header and returns 401 Unauthorized.
Symptom 3: Manually calling POST /admin/restart again in the browser/curl with the correct authorization: Bearer <key> returns {"ok":true}, but the container process does not actually restart (start time unchanged). Therefore, the configuration is not reloaded, and models with enabled:true never take effect.
Steps to Reproduce
- Set
BRIDGE_API_KEY=sk-xxx in .env (with the sk- prefix)
- Start Bridge in Docker and access the Dashboard at
http://<IP>:9992
- Enable a model in the Dashboard (e.g.
deepseek/deepseek-v4.1-flash)
- Click “JSON Save” → succeeds, prompts restart
- Click “Restart Bridge” → 401 Unauthorized
- Manually call
POST /admin/restart with the correct key via curl → returns ok, but the container process does not restart and the model remains ineffective
Root Cause Analysis
Cause A: The auth() function does not use pendingBridgeKey (src/dashboard.ts)
function auth(){
const key = currentBridgeAuthKey() || (!pendingBridgeKey ? fullBridgeKey() : '') || '';
return key ? {'authorization':'Bearer '+key,...} : {'content-type':'application/json'}
}
- After the user sets a key via “💾/🎲”,
pendingBridgeKey becomes truthy
- At this point,
currentBridgeAuthKey() returns empty (no key in localStorage + server returns [REDACTED])
- Also, when
pendingBridgeKey is truthy, !pendingBridgeKey is false, so fullBridgeKey() is not called
- Therefore,
auth() returns headers without the Authorization header → server returns 401
Packet capture evidence: The save request (successful) includes the authorization header; however, the immediately following restart request (from the same operation flow) does not include the authorization header. The reason is that after a successful save, render()→syncBridgeKey() clears the “Client API Key” input field, and pendingBridgeKey is left in an abnormal state.
Suggested fix:
const key = currentBridgeAuthKey() || pendingBridgeKey || fullBridgeKey() || '';
Cause B: restartBridge() is a no-op under Docker without systemd (src/server.ts)
function restartBridge(): void {
if (process.platform === "linux") {
const supervisedBySystemd = Boolean(process.env.INVOCATION_ID || process.env.SYSTEMD_EXEC_PID);
if (supervisedBySystemd || process.env.COMMANDCODE_BRIDGE_RESTART_MODE === "exit") {
setTimeout(() => process.exit(0), 100).unref?.();
}
return; // ← Under Docker without systemd and without COMMANDCODE_BRIDGE_RESTART_MODE, it returns directly and does nothing
}
// macOS launchctl logic
}
In a Docker container (non-systemd), if neither INVOCATION_ID/SYSTEMD_EXEC_PID is present nor COMMANDCODE_BRIDGE_RESTART_MODE=exit is set, restartBridge() does nothing. POST /admin/restart returns {"ok":true}, but the process does not exit, the container does not restart, and the running configuration is not reloaded → the saved model enablement does not take effect.
This needs to be clearly documented in the Docker deployment docs (e.g. set restart: unless-stopped + COMMANDCODE_BRIDGE_RESTART_MODE=exit, or manually run docker restart).
Recommendations
- Fix the
auth() function so that pendingBridgeKey also participates in authentication
- Add the prerequisites for
restartBridge() to take effect in the Docker deployment documentation (systemd, or COMMANDCODE_BRIDGE_RESTART_MODE=exit + container auto-restart)
Environment
- Version: 1.53.0.a
- Deployment: Docker container (non-systemd)
- Access:
http://192.168.124.3:9992
- BRIDGE_API_KEY: starts with
sk-
[Bug] Dashboard 保存后无法通过重启生效 / Dashboard-saved config does not take effect after restart
中文
问题描述
在 Docker 容器中部署(非 systemd 托管),通过 Dashboard 管理模型时遇到两个连锁问题,导致模型启用后无法生效:
现象 1:Dashboard 上保存配置(带上了正确的
authorization: Bearer <BRIDGE_API_KEY>)能成功,保存后提示“需要重启”。现象 2:点击「重启 Bridge」按钮时,请求没有携带
authorization头,返回401 Unauthorized。现象 3:手动在浏览器/curl 中带上正确的
authorization: Bearer <key>重新调用POST /admin/restart,返回{"ok":true},但容器进程实际没有重启(启动时间不变),因此配置没有重新加载,已启用(enabled:true)的模型始终不生效。复现步骤
.env设置BRIDGE_API_KEY=sk-xxx(带sk-前缀)http://<IP>:9992访问 Dashboarddeepseek/deepseek-v4.1-flash)POST /admin/restart→ 返回 ok,但容器进程未重启,模型仍未启用根本原因分析
问题 A:
auth()函数未使用pendingBridgeKey(src/dashboard.ts)pendingBridgeKey变为真值currentBridgeAuthKey()(localStorage 无 key + 服务端返回[REDACTED])返回空pendingBridgeKey为真时,!pendingBridgeKey为 false,fullBridgeKey()不会被调用auth()返回不携带 Authorization 头的 headers → 服务端 401抓包证据:保存请求(成功)带
authorization头;但紧接着的重启请求(来自同一操作流)没有authorization头。原因是保存成功后render()→syncBridgeKey()把「客户端 API Key」输入框清空,且pendingBridgeKey处于异常状态。建议修复:
问题 B:Docker 非 systemd 下
restartBridge()是 no-op(src/server.ts)在 Docker 容器(非 systemd)中,如果既没有
INVOCATION_ID/SYSTEMD_EXEC_PID,也没设置COMMANDCODE_BRIDGE_RESTART_MODE=exit,restartBridge()什么都不做。POST /admin/restart返回{"ok":true},但进程没退出、容器没重启、运行中的配置没重新加载 → 保存的模型启用不生效。这需要在 Docker 部署文档中明确说明(如设置
restart: unless-stopped+COMMANDCODE_BRIDGE_RESTART_MODE=exit,或手动docker restart)。建议
auth()函数,让pendingBridgeKey也参与认证restartBridge()的生效前提(systemd 或COMMANDCODE_BRIDGE_RESTART_MODE=exit+ 容器 auto-restart)环境
http://192.168.124.3:9992sk-开头English
Description
Deployed in a Docker container (not managed by systemd). When managing models through the Dashboard, two cascading issues occur, causing enabled models to remain ineffective:
Symptom 1: Saving the configuration in the Dashboard (with the correct
authorization: Bearer <BRIDGE_API_KEY>) succeeds, and after saving it prompts “restart required”.Symptom 2: When clicking the “Restart Bridge” button, the request does not include the
authorizationheader and returns401 Unauthorized.Symptom 3: Manually calling
POST /admin/restartagain in the browser/curl with the correctauthorization: Bearer <key>returns{"ok":true}, but the container process does not actually restart (start time unchanged). Therefore, the configuration is not reloaded, and models withenabled:truenever take effect.Steps to Reproduce
BRIDGE_API_KEY=sk-xxxin.env(with thesk-prefix)http://<IP>:9992deepseek/deepseek-v4.1-flash)POST /admin/restartwith the correct key via curl → returns ok, but the container process does not restart and the model remains ineffectiveRoot Cause Analysis
Cause A: The
auth()function does not usependingBridgeKey(src/dashboard.ts)pendingBridgeKeybecomes truthycurrentBridgeAuthKey()returns empty (no key in localStorage + server returns[REDACTED])pendingBridgeKeyis truthy,!pendingBridgeKeyis false, sofullBridgeKey()is not calledauth()returns headers without the Authorization header → server returns 401Packet capture evidence: The save request (successful) includes the
authorizationheader; however, the immediately following restart request (from the same operation flow) does not include theauthorizationheader. The reason is that after a successful save,render()→syncBridgeKey()clears the “Client API Key” input field, andpendingBridgeKeyis left in an abnormal state.Suggested fix:
Cause B:
restartBridge()is a no-op under Docker without systemd (src/server.ts)In a Docker container (non-systemd), if neither
INVOCATION_ID/SYSTEMD_EXEC_PIDis present norCOMMANDCODE_BRIDGE_RESTART_MODE=exitis set,restartBridge()does nothing.POST /admin/restartreturns{"ok":true}, but the process does not exit, the container does not restart, and the running configuration is not reloaded → the saved model enablement does not take effect.This needs to be clearly documented in the Docker deployment docs (e.g. set
restart: unless-stopped+COMMANDCODE_BRIDGE_RESTART_MODE=exit, or manually rundocker restart).Recommendations
auth()function so thatpendingBridgeKeyalso participates in authenticationrestartBridge()to take effect in the Docker deployment documentation (systemd, orCOMMANDCODE_BRIDGE_RESTART_MODE=exit+ container auto-restart)Environment
http://192.168.124.3:9992sk-