April 19, 2026 • 版本: 2026.4.14

Telegram: commands.native 在启动时未能注册 setMyCommands

尽管在 OpenClaw 2026.4.14 中的配置正确,但原生 Telegram 机器人命令未能通过 setMyCommands 成功注册,导致命令菜单从机器人界面中缺失。

🔍 症状

主要表现

Telegram 机器人正常接收和处理消息,但在网关启动时原生命令注册从未发生。

诊断输出模式

缺失的日志条目 bash

Search for setMyCommands in logs

grep -i “setMyCommands|setMyCommands|commands.native|BOT_COMMANDS” /var/log/openclaw/gateway.log

Expected: Multiple entries like:

[INFO] TelegramProvider: Registering native commands via setMyCommands

[INFO] TelegramProvider: Successfully registered 8 bot commands

[DEBUG] bot.api.setMyCommands called with

Actual: Zero matches

无自动完成菜单 在 Telegram 私信中输入 / 时,不显示命令菜单。斜杠命令自动补全功能需要在初始化期间调用 setMyCommands

配置看起来正确 json { “channels”: { “telegram”: { “enabled”: true, “token”: “123456789:ABCdefGHI…”, “commands”: { “native”: true, “nativeSkills”: true } } } }

CLI 验证命令

bash

Check if commands are registered via Telegram API

curl -s “https://api.telegram.org/bot/getMyCommands” | jq .

Expected after successful registration:

{

“ok”: true,

“result”: [

{“command”: “help”, “description”: “Show available commands”},

{“command”: “status”, “description”: “Check system status”},

]

}

Actual (bug present):

{

“ok”: true,

“result”: []

}

静默失败特征

  • 没有 ERRORWARN 级别的日志条目
  • 网关启动成功完成(退出代码 0)
  • Telegram 机器人正常响应消息
  • 手动调用时技能命令正常执行
  • 仅缺少命令菜单/自动补全功能

🧠 根因分析

架构背景

setMyCommands 注册发生在 Telegram provider 的初始化序列中。代码路径存在于 dist/bot-BwMz6R6-.js 中,但由于一个或多个早期返回条件而永远无法到达。

主要根因

1. 配置 Schema 不匹配

Telegram provider 将 commands.native 作为字符串值进行检查,但配置 schema 验证器会将 "true" 强制转换为布尔值 true,或将 "auto" 强制转换为意外的枚举值。条件检查静默失败:

javascript // In provider initialization (inferred from behavior) if (config.commands?.native !== ‘auto’ && config.commands?.native !== true) { return early; // Exits before setMyCommands is called }

// Problem: If config.commands.native is boolean true (not string ’true’) // or if the path is channels.telegram.commands.native vs nested structure // The comparison evaluates incorrectly

2. 异步初始化竞态条件

Telegram provider 可能在命令注册表填充之前初始化:

Gateway Start │ ├── Load Channels Config │ │ │ └── TelegramProvider.init() │ │ │ └── bot.api.setMyCommands(retryCommands) │ │ │ └── retryCommands = [] ← Commands not yet loaded │ └── Load Plugins/Skills │ └── Populate command registry

当在 provider 初始化时计算 retryCommands 时,技能命令列表为空,因为插件在 provider 初始化之后才加载。

3. Promise 链中的错误吞没

setMyCommands 调用包装在带有 .catch() 处理程序的 Promise 中,该处理程序吞没错误而不记录日志:

javascript // Inferred from symptom “no error, no warning” bot.api.setMyCommands(retryCommands) .then(() => logger.info(‘Commands registered’)) .catch(err => { // Error swallowed here - no logging // void err or empty catch block });

4. 功能标志覆盖

环境变量或功能标志可能全局禁用了命令注册:

bash

These environment variables would prevent registration

OPENCLAW_TELEGRAM_COMMANDS_ENABLED=false OPENCLAW_DISABLE_NATIVE_COMMANDS=1 TELEGRAM_SKIP_COMMAND_REGISTRATION=true

5. Provider 条件评估错误

Telegram provider 可能有一个评估错误的守卫条件:

javascript // Probable code path issue class TelegramProvider { async start() { // Bug: Checks wrong property path if (!this.config.channel?.commands?.native) { return this.startPolling(); // Skips command registration }

    // This code is never reached
    await this.registerCommands();
}

}

// Correct path should be: if (!this.config.commands?.native) { … }

故障序列图

┌─────────────────────────────────────────────────────────────┐ │ Gateway Startup │ ├─────────────────────────────────────────────────────────────┤ │ 1. Config.load() → Merges JSON + env vars │ │ └── channels.telegram.commands.native: true (boolean) │ │ │ │ 2. PluginRegistry.load() │ │ └── Skills loaded, command registry empty │ │ │ │ 3. TelegramProvider.init() │ │ └── Checks: config.commands?.native !== ‘auto’ │ │ └── Boolean true !== String ‘auto’ → exits early │ │ │ │ 4. setMyCommands() never called │ │ └── retryCommands: [] │ │ │ │ 5. Gateway ready, polling active │ │ └── Commands not registered, no errors logged │ └─────────────────────────────────────────────────────────────┘

环境特定触发因素

平台触发器机制
macOS LaunchAgent顺序依赖Plist 按字母顺序加载服务
Docker配置卷挂载在环境变量覆盖应用之前解析 JSON
Linux systemd时序问题After=network.target 但不是 openclaw-ready.service
Windows Service注册表状态NSSM 在服务依赖项之前读取配置

🛠️ 逐步修复

修复策略 1:配置路径修正

最可能的问题是配置路径不正确或类型不匹配。OpenClaw 2026.4.14 期望特定的 schema 结构。

步骤 1:验证配置 Schema

bash

Check actual loaded configuration

cat ~/.openclaw/openclaw.json | jq ‘.channels.telegram.commands’

步骤 2:应用正确的配置

编辑您的 openclaw.json

json // BEFORE (incorrect - may be wrong path or type) { “channels”: { “telegram”: { “commands”: { “native”: true } } } }

// AFTER (correct schema) { “channels”: { “telegram”: { “commands”: { “native”: “auto” } } } }

注意: 使用字符串 "auto" 而不是布尔值 true。代码与字符串字面量 'auto'true(字符串)进行比较,而不是与布尔值 true 进行比较。

步骤 3:重启网关

bash

macOS LaunchAgent

launchctl unload ~/Library/LaunchAgents/ai.openclaw.gateway.plist launchctl load ~/Library/LaunchAgents/ai.openclaw.gateway.plist

Linux systemd

sudo systemctl restart openclaw-gateway

Docker

docker restart openclaw-gateway

Direct (development)

pkill -f openclaw-gateway && openclaw gateway start


修复策略 2:手动命令注册(立即生效)

在调查启动问题的同时获得即时缓解:

步骤 1:识别所需命令

bash

List all registered commands from OpenClaw

grep -r “BOT_COMMANDS|registerCommand|command.*description”
~/.openclaw/node_modules/openclaw/dist/ 2>/dev/null
| head -30

步骤 2:通过 Telegram API 注册

bash

Replace with your bot token

curl -X POST “https://api.telegram.org/bot/setMyCommands”
-H “Content-Type: application/json”
-d ‘{ “commands”: [ {“command”: “help”, “description”: “Show available commands and usage”}, {“command”: “status”, “description”: “Display system status and health”}, {“command”: “new”, “description”: “Start a new conversation thread”}, {“command”: “reset”, “description”: “Reset conversation context”}, {“command”: “model”, “description”: “Show or change the active AI model”}, {“command”: “skills”, “description”: “List available skill plugins”} ], “scope”: {“type”: “default”} }’

步骤 3:验证注册

bash curl -s “https://api.telegram.org/bot/getMyCommands” | jq .

预期输出: json { “ok”: true, “result”: [ {“command”: “help”, “description”: “Show available commands and usage”}, {“command”: “status”, “description”: “Display system status and health”} ] }


修复策略 3:环境变量覆盖

如果配置路径正确但 provider 仍然跳过注册:

步骤 1:设置调试环境变量

bash

Add to your shell profile or LaunchAgent plist EnvironmentVariables

export OPENCLAW_TELEGRAM_COMMANDS_DEBUG=1 export DEBUG=openclaw:telegram:commands

步骤 2:清除运行时缓存

bash rm -rf ~/.openclaw/cache/* rm -rf ~/.openclaw/runtime/state.json

步骤 3:使用详细日志重启

bash

Run with debug output

openclaw gateway start –log-level debug 2>&1 | grep -i “command|setMy”


修复策略 4:代码级热修复

如果您有修改运行时代码的权限:

步骤 1:定位 Provider 文件

bash

Find the Telegram provider

find ~/.openclaw/node_modules -name “provider-telegram*.js” -o
-name “TelegramProvider.js” 2>/dev/null

步骤 2:修补条件检查

找到早期返回条件并修复比较:

javascript // BEFORE (buggy) if (config.commands?.native !== ‘auto’ && config.commands?.native !== true) { return early; }

// AFTER (fixed) if (config.commands?.native === false || config.commands?.native === ‘false’) { return early; }

步骤 3:在 Catch 块中添加错误日志

javascript // Find the setMyCommands call and add logging try { await bot.api.setMyCommands(retryCommands); logger.info(TelegramProvider: Registered ${retryCommands.length} native commands); } catch (err) { logger.error(‘TelegramProvider: Failed to register commands’, { error: err.message }); // Don’t swallow - let it propagate }


修复策略 5:Provider 启动顺序修复

如果问题是与插件加载的竞态条件:

步骤 1:添加启动依赖

对于 LaunchAgent (ai.openclaw.gateway.plist): xml KeepAlive SuccessfulExit StartInterval 5

对于 systemd (openclaw-gateway.service): ini [Unit] After=network.target After=time-sync.target Wants=time-sync.target

[Service] ExecStartPre=/bin/sleep 3 Restart=on-failure RestartSec=5

🧪 验证

立即验证步骤

步骤 1:检查网关日志中的命令注册

bash

Tail logs with command registration filter

tail -f /var/log/openclaw/gateway.log 2>/dev/null | grep -E “setMyCommands|commands.*registered|native.*command”

Or for recent startup

grep -E “setMyCommands|commands.*registered|native.*command”
/var/log/openclaw/gateway.log | tail -20

预期输出:

[TIMESTAMP] INFO TelegramProvider: Initializing native command registration [TIMESTAMP] INFO TelegramProvider: Built-in commands loaded: help, status, new, reset, model [TIMESTAMP] INFO TelegramProvider: Skill commands loaded: 4 commands [TIMESTAMP] INFO TelegramProvider: Calling setMyCommands with 8 commands [TIMESTAMP] INFO TelegramProvider: Successfully registered 8 bot commands via setMyCommands

实际输出(bug 仍存在):

No matching entries found

步骤 2:通过 Telegram API 验证

bash

Replace with your bot token

TELEGRAM_TOKEN=“123456789:ABCdefGHI…”

curl -s “https://api.telegram.org/bot${TELEGRAM_TOKEN}/getMyCommands" | jq .

预期: json { “ok”: true, “result”: [ { “command”: “help”, “description”: “Show available commands” }, { “command”: “status”, “description”: “Display system status” } ] }

实际(未修复): json { “ok”: true, “result”: [] }

步骤 3:在 Telegram 中测试命令菜单

  1. 打开与 Telegram 机器人的私信
  2. 输入 / — 命令菜单应出现并带有自动补全
  3. 尝试每个命令:/help/status/new/reset

预期: 输入 / 时立即出现命令菜单

实际(未修复): 不显示菜单;必须手动输入命令


自动化验证脚本

bash #!/bin/bash

verify-telegram-commands.sh

TELEGRAM_TOKEN="${OPENCLAW_TELEGRAM_TOKEN:-}”

if [ -z “$TELEGRAM_TOKEN” ]; then echo “ERROR: OPENCLAW_TELEGRAM_TOKEN not set” exit 1 fi

echo “=== Telegram Bot Commands Verification ===” echo ""

Check registered commands

RESPONSE=$(curl -s “https://api.telegram.org/bot${TELEGRAM_TOKEN}/getMyCommands") COUNT=$(echo “$RESPONSE” | jq ‘.result | length’)

echo “Registered commands: $COUNT” echo “$RESPONSE” | jq -r ‘.result[] | " /” + .command + " - " + .description’

if [ “$COUNT” -gt 0 ]; then echo "" echo “✓ SUCCESS: Commands are registered” exit 0 else echo "" echo “✗ FAILURE: No commands registered” exit 1 fi

运行验证: bash chmod +x verify-telegram-commands.sh ./verify-telegram-commands.sh

预期输出:

=== Telegram Bot Commands Verification ===

Registered commands: 6 /help - Show available commands /status - Display system status /new - Start a new conversation /reset - Reset conversation context /model - Show or change AI model /skills - List skill plugins

✓ SUCCESS: Commands are registered


日志分析清单

应用修复后,验证这些日志条目在启动时出现:

日志条目状态含义
TelegramProvider: Initializing native command registration✓ 必需Provider 检测到原生命令已启用
TelegramProvider: Built-in commands loaded✓ 必需核心命令已枚举
TelegramProvider: Skill commands loaded: N commands✓ 如果 nativeSkills 启用插件命令已加载
TelegramProvider: Calling setMyCommands with N commands✓ 必需API 调用已启动
TelegramProvider: Successfully registered N bot commands✓ 必需API 调用成功

⚠️ 常见陷阱

配置陷阱

1. 类型强制转换不匹配

json // INCORRECT - boolean instead of string “native”: true

// CORRECT - string value “native”: “auto”

Provider 代码可能与字符串字面量进行比较。在 JavaScript 中,布尔值 true 永远不会等于字符串 "true"

2. 嵌套路径错误

json // INCORRECT - wrong nesting “telegram”: { “plugin”: { “commands”: { “native”: true } } }

// CORRECT - expected path “telegram”: { “commands”: { “native”: “auto” } }

3. 环境变量覆盖被忽略

bash

Set in shell but not passed to LaunchAgent

export OPENCLAW_TELEGRAM_COMMANDS_ENABLED=true # Ignored by LaunchAgent

Correct: Add to plist EnvironmentVariables

EnvironmentVariables OPENCLAW_TELEGRAM_COMMANDS_ENABLED true

平台特定陷阱

macOS LaunchAgent

陷阱症状解决方案
Config cached by launchdChanges don’t take effect运行 launchctl unload/load 循环
User-level vs system plistPermission denied检查 ~/Library/LaunchAgents/ vs /Library/LaunchAgents/
Stale PID preventing restart“Already running”launchctl remove ai.openclaw.gateway && launchctl load

Docker Container

陷阱症状解决方案
Volume mount orderConfig not found在应用卷之前挂载配置卷
ENV var timingOverrides not applied使用 docker-compose.override.yml
Network isolationAPI calls fail确保容器可以访问 api.telegram.org

Linux Systemd

陷阱症状解决方案
Service starts too earlyRace condition添加 ExecStartPre=/bin/sleep 5
Journal truncationLogs missingjournalctl -u openclaw-gateway -n 1000
SELinux/AppArmorNetwork blockedsetsebool -P nis_enabled 1

运行时陷阱

1. Token 不匹配

如果 openclaw.json 中使用的机器人 token 与环境变量中的 token 不同,getMyCommandssetMyCommands 将引用不同的机器人。

bash

Verify token consistency

jq ‘.channels.telegram.token’ ~/.openclaw/openclaw.json echo $OPENCLAW_TELEGRAM_TOKEN

2. BotFather 命令范围

Telegram 机器人可以在不同的范围内注册命令:

  • default - 所有聊天
  • commands_in_private - 仅私人聊天
  • chat_id 的每聊范围

如果之前通过 BotFather 使用某个范围设置了命令,setMyCommands 可能无法覆盖它们。

bash

Clear all command scopes

curl -X POST “https://api.telegram.org/bot/deleteMyCommands”
-H “Content-Type: application/json”
-d ‘{“scope”: {“type”: “all_private_chats”}}’

curl -X POST “https://api.telegram.org/bot/deleteMyCommands”
-H “Content-Type: application/json”
-d ‘{}’ # Delete default scope too

3. 速率限制

Telegram 对 setMyCommands 的速率限制约为每秒 1 次调用。如果在调试期间网关快速重启,API 可能会拒绝调用。

bash

Check for rate limit errors

grep -i “Too Many Requests|retry_after” /var/log/openclaw/gateway.log

4. 机器人模式限制

某些模式(如 inline-only、受限)的机器人无法使用 setMyCommands

开发陷阱

热重载未重载 Provider

某些热重载实现会重新初始化插件但不重新初始化 Telegram provider。命令永远不会被重新注册。

bash

Full restart required, not just config reload

pkill -f openclaw openclaw gateway start

调试日志使错误静默

较高的 logLevel 设置(debugtrace)有时会导致错误被记录在被过滤掉的级别。

bash

Explicitly enable all Telegram-related logs

openclaw gateway start –log-level debug –log-filter “telegram,commands,provider”

🔗 相关错误

直接相关错误

错误代码描述关联
BOT_COMMANDS_TOO_MUCH超过 100 个命令时的 Telegram API 错误注册过多技能时 setMyCommands 失败
TELEGRAM_API_ERROR_400Telegram API 错误请求setMyCommands 发送格式错误的命令负载
TELEGRAM_API_ERROR_401未授权无效的机器人 token 导致 setMyCommands 失败
TELEGRAM_API_ERROR_429请求过多setMyCommands 调用的速率限制

历史相关问题

问题描述可能性
lossless-claw 上下文引擎错误重启期间的 LCM 错误(问题中已注明)次要问题,独立解决
插件初始化时序技能在 provider 初始化之后加载v2026.x 中出现的竞态条件模式
版本之间的配置 schema 变更破坏性配置格式变更版本发布中的常见问题
Provider 生命周期变更v2026.4 中 Telegram provider 重构代码路径 bug 的直接原因

其他渠道的类似症状

渠道相关症状区分特征
Discord斜杠命令未注册不同的 API(/applications 端点)
SlackApp home 命令缺失使用 apps.connections.install 流程
Matrix命令前缀不显示使用房间状态事件代替

外部参考

  • Telegram Bot API: setMyCommandshttps://core.telegram.org/bots/api#setmycommands
  • Telegram Bot API: getMyCommandshttps://core.telegram.org/bots/api#getmycommands
  • grammY Commands Pluginhttps://grammy.dev/plugins/commands
  • OpenClaw Config Schema~/.openclaw/node_modules/openclaw/schema/config.json

相关日志模式

在诊断类似问题时,在网关日志中搜索这些模式:

bash

All Telegram-related logging

grep -E “TelegramProvider|Telegram.*provider|telegram” /var/log/openclaw/gateway.log

Command registration attempts

grep -E “setMyCommands|register.*command|command.*registration” /var/log/openclaw/gateway.log

API errors

grep -E “api.*error|api.*fail|telegram.*error” /var/log/openclaw/gateway.log

Configuration loading

grep -E “config.*load|channels.*init|provider.*start” /var/log/openclaw/gateway.log

依据与来源

本故障排除指南由 FixClaw 智能管线从社区讨论中自动合成。