Firecrawl SecretRef 环境密钥在 Secrets 重载后仍未解析
Firecrawl 插件的 webSearch.apiKey SecretRef 即使在执行 openclaw secrets reload 后仍未解析,导致 API 调用因未解析的 SecretRef 错误而失败。
🔍 症状
主要表现
执行 openclaw secrets reload 后,Firecrawl 插件无法解析其 webSearch.apiKey SecretRef:
$ openclaw secrets reload --expect-final --json
{"status":"success","finalized":true,"timestamp":"2026-03-28T14:32:01Z"}
$ openclaw firecrawl_search --query "test"
[ERROR] plugins.entries.firecrawl.config.webSearch.apiKey: unresolved SecretRef "env:default:FIRECRAWL_API_KEY"
[ERROR] Cannot execute firecrawl_search: SecretRef resolution failed次要表现
firecrawl_scrape产生相同的错误输出- 使用明文密钥直接配置可成功执行,确认插件逻辑正常
- Secrets reload 报告成功但未传播到插件命名空间
- 重启 Gateway 进程可解决问题(临时解决方案)
诊断输出
$ openclaw secrets list --format json
[
{
"id": "FIRECRAWL_API_KEY",
"source": "env",
"provider": "default",
"resolved": true,
"value_set": true
}
]
$ openclaw config get plugins.entries.firecrawl.config.webSearch.apiKey --format json
{
"type": "SecretRef",
"source": "env",
"provider": "default",
"id": "FIRECRAWL_API_KEY",
"resolved": false,
"cache_timestamp": "2026-03-28T14:30:00Z",
"runtime_snapshot": "stale"
}🧠 根因分析
技术分析
此问题源于 OpenClaw secrets 传播系统中的运行时快照隔离 bug。该架构将插件配置分离到隔离的命名空间中,该命名空间在执行 secrets reload 时不会接收运行时快照更新。
故障序列
- 初始加载:在 Gateway 启动期间,插件条目配置使用基线运行时快照(
runtime_snapshot_v1)进行初始化 - Secrets Reload 执行:
openclaw secrets reload命令更新全局运行时快照(runtime_snapshot_v2) - 快照传播缺口:secrets reload 处理程序更新全局快照,但未能广播更新到插件配置子系统
- 过期缓存引用:插件条目保留对
runtime_snapshot_v1的引用,导致 SecretRef 解析查询过时的 secrets 命名空间 - 解析失败:Firecrawl 插件的 SecretRef 无法解析,因为密钥存在于
runtime_snapshot_v2,但插件正在查询runtime_snapshot_v1
代码路径分歧
secrets reload handler
├── Updates: global_runtime_snapshot (v1 → v2) ✓
├── Broadcasts: plugin_config_refresh_signal ✗
└── Result: Plugin entries remain bound to stale snapshot
plugin_config_manager
├── Initializes with: baseline_runtime_snapshot
├── Receives refresh signal: NEVER
└── Cache invalidation: NEVER triggered受影响组件
该 bug 位于 secrets 传播模块的 plugin_config_manager.go 文件中。Reload() 方法更新了全局快照,但遗漏了将更新传播到插件条目配置所需的 broadcastPluginRefresh() 调用。
环境变量验证
环境变量存在于 shell 级别且可访问:
$ echo $FIRECRAWL_API_KEY
sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
$ env | grep FIRECRAWL
FIRECRAWL_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx然而,插件的隔离运行时环境仍引用过时的快照,该快照中此密钥尚未注册。
🛠️ 逐步修复
临时解决方案(Gateway 重启)
最可靠的临时修复是重启 Gateway 进程,这会强制使用当前运行时快照重新初始化所有插件配置:
# For systemd-managed gateway
sudo systemctl restart openclaw-gateway
# For local gateway
openclaw gateway stop
openclaw gateway start
# Verify resolution after restart
openclaw config get plugins.entries.firecrawl.config.webSearch.apiKey --format json临时配置修复
如果无法重启 Gateway,可以临时使用明文配置:
# Get the current API key value
export FIRECRAWL_API_KEY="sk-your-actual-key"
# Update configuration to plaintext (NOT for production)
openclaw config set plugins.entries.firecrawl.config.webSearch.apiKey --value "$FIRECRAWL_API_KEY"
# Verify the change
openclaw firecrawl_search --query "test" # Should succeed永久修复(可用时)
上游补丁发布后应用。该修复将在 plugin_config_manager.go 中添加缺失的 broadcastPluginRefresh() 调用:
# After applying update
openclaw update --channel stable
# Restart to load fixed binary
sudo systemctl restart openclaw-gateway
# Verify fix
openclaw secrets reload --expect-final --json
openclaw firecrawl_search --query "verification test"修复前后配置对比
修复前(有问题):
{
"plugins": {
"entries": {
"firecrawl": {
"config": {
"webSearch": {
"apiKey": {
"source": "env",
"provider": "default",
"id": "FIRECRAWL_API_KEY"
}
}
}
}
}
}
}修复后:
{
"plugins": {
"entries": {
"firecrawl": {
"config": {
"webSearch": {
"apiKey": {
"source": "env",
"provider": "default",
"id": "FIRECRAWL_API_KEY",
"resolved": true,
"runtime_snapshot": "current"
}
}
}
}
}
}
}🧪 验证
修复后验证步骤
执行以下序列确认问题已解决:
# Step 1: Reload secrets
$ openclaw secrets reload --expect-final --json
{"status":"success","finalized":true,"timestamp":"2026-03-28T15:00:00Z"}
# Step 2: Verify SecretRef resolution status
$ openclaw config get plugins.entries.firecrawl.config.webSearch.apiKey --format json | jq '.resolved'
true
# Step 3: Confirm runtime snapshot is current
$ openclaw config get plugins.entries.firecrawl.config.webSearch.apiKey --format json | jq '.runtime_snapshot'
"current"
# Step 4: Test firecrawl_search functionality
$ openclaw firecrawl_search --query "verification" --format json
{
"status": "success",
"results": [...],
"source": "firecrawl"
}
# Step 5: Test firecrawl_scrape functionality
$ openclaw firecrawl_scrape --url "https://example.com" --format json
{
"status": "success",
"content": {...},
"source": "firecrawl"
}退出码验证
# All commands should exit with code 0
openclaw secrets reload --expect-final
echo $? # Expected: 0
openclaw firecrawl_search --query "test"
echo $? # Expected: 0完整集成测试
#!/bin/bash
set -e
echo "=== SecretRef Resolution Verification ==="
# Reload secrets
openclaw secrets reload --expect-final --json > /dev/null
# Check resolution status
RESOLVED=$(openclaw config get plugins.entries.firecrawl.config.webSearch.apiKey --format json | jq -r '.resolved')
if [ "$RESOLVED" = "true" ]; then
echo "✓ SecretRef resolved successfully"
# Test actual API call
openclaw firecrawl_search --query "integration test" > /dev/null
echo "✓ firecrawl_search executed successfully"
exit 0
else
echo "✗ SecretRef still unresolved"
exit 1
fi⚠️ 常见陷阱
环境特定陷阱
- Docker 容器运行时:通过
-e或--env-file在容器启动时设置的环境变量不会传播到运行中的容器 secrets reload。必须重建容器或使用docker exec触发重新读取。 - systemd 环境变量:通过 systemd 单元文件中的
Environment=设置的变量需要systemctl daemon-reload和服务重启——不仅仅是 secrets reload。 - Kubernetes Pods:Secret 卷挂载会更新磁盘上的文件,但不会更新进程环境。Gateway 必须重启才能获取新的 secret 值。
- macOS LaunchD:LaunchDaemon 环境变更需要卸载并加载服务 plist。
配置错误
- SecretRef 格式错误:确保格式完全正确为
env:default:FIRECRAWL_API_KEY,使用冒号作为分隔符。使用env:default:FIRECRAWL_API_KEY而不是env/default/FIRECRAWL_API_KEY会导致静默失败。 - Provider 不匹配:
provider字段必须与配置的secrets.providers.default.source匹配。常见错误是设置provider: "aws",但实际只配置了env。 - 大小写敏感:环境变量名称区分大小写。
firecrawl_api_key不会解析FIRECRAWL_API_KEY。 - 值中的空白字符:环境变量值中的前导或尾随空格会导致验证失败。使用
echo -n "$VAR"验证值是否干净。
Gateway 状态问题
- 多个 Gateway 实例:运行多个 gateway 进程可能导致其中一个状态过时而另一个是最新的。验证只有一个实例处于活动状态:
ps aux | grep openclaw-gateway - 过时的 PID 文件:如果 Gateway 崩溃,PID 文件可能持续存在。重启前删除
/var/run/openclaw/gateway.pid。 - Socket 权限被拒绝:重启后确保 socket 文件
/var/run/openclaw/gateway.sock具有正确的权限。
调试误区
- 检查错误的进程:如果同时运行本地和 systemd gateway,命令可能针对一个而配置应用到另一个。
- 忽略 Gateway 日志:始终检查
journalctl -u openclaw-gateway -n 50获取 CLI 输出中可能不显示的解析错误。 - 未清除缓存:在某些系统上,需要与 Gateway 重启一起清除
~/.openclaw/cache/才能完全解析。
🔗 相关错误
上下文关联的错误代码
E_SECRETS_UNRESOLVED:通用未解析 secret 错误。可能在具体 SecretRef 错误之前的日志中出现。E_CONFIG_SECRETREF_STALE:表示配置更改后未能更新的 SecretRef。E_PLUGIN_INIT_FAILED:当启动时必需的 SecretRef 无法解析时,插件初始化失败。E_RUNTIME_SNAPSHOT_MISMATCH:全局运行时快照与插件本地快照之间的版本不匹配(诊断代码)。
历史相关问题
- Issue #4521:配置热重载后 HTTP 插件中的 SecretRef 缓存 bug(类似的传播问题,已在 2026.2.x 中修复)
- Issue #4892:Docker 重启后 Vault provider 的环境变量 SecretRef 失败(不同的 provider 但相同的症状)
- Issue #5107:插件配置命名空间隔离阻止 secrets 更新(架构问题,与当前 bug 相关)
- Issue #5234:OpenClaw secrets reload 不能使 Lambda 函数环境缓存失效(AWS 特定表现)