Skip to content

bug(messaging) channels stop <name> does not stop the bridge through rebuild — openclaw.json still bakes the channel in #3453

@sandl99

Description

@sandl99

Affected channels: telegram, discord, slack, wechat (any channel registered via MESSAGING_CHANNELS)

Affected versions: Reproduces on main after #3395 landed. #3395 fixed the recovery side (channels start can find the channel afterward) but did not address the build-time disable filter.

Summary

After nemoclaw <sandbox> channels stop <name> followed by a rebuild, the new sandbox image's /opt/nemoclaw/openclaw.json still contains the channel's config, and the bridge starts on next boot. The host-side registry correctly records disabledChannels: [<name>], but the
build-time filter in createSandbox reads from a registry entry that has been wiped earlier in rebuildSandbox, so the filter sees [] and bakes the channel in.

Reproduction

# Onboard a sandbox with at least one messaging channel, e.g. telegram.
nemoclaw onboard --agent openclaw   # answer prompts; enable telegram

# Stop the channel.
nemoclaw <sandbox> channels stop telegram
# Answer "y" when asked to rebuild.

# Inspect the new image's openclaw.json.
docker exec <sandbox-container> cat /opt/nemoclaw/openclaw.json | jq .channels
# OR:
docker exec <sandbox-container> grep -i telegram /opt/nemoclaw/openclaw.json

Expected

openclaw.json does not contain the telegram channel; the bridge does not start; gateway logs show no telegram-bridge provider attached.

Actual

openclaw.json still contains the telegram channel config, and the telegram bridge starts on sandbox boot. Host registry has the correct disabledChannels: ["telegram"] and messagingChannels: [..., "telegram"], but those values aren't reflected in the baked image.

Root cause

The wipe-and-rebuild order in rebuildSandbox makes the registry temporarily empty while createSandbox runs:

  1. src/lib/actions/sandbox/rebuild.ts:486removeSandboxRegistryEntry(sandboxName) wipes the registry entry (including disabledChannels).
  2. src/lib/onboard.ts:5425 (inside createSandbox) — const disabledChannels = registry.getDisabledChannels(sandboxName) returns [] because the entry no longer exists.
  3. src/lib/onboard.ts:5460 — the messagingTokenDefs filter .filter(({envKey}) => !disabledEnvKeys.has(envKey)) is a no-op (empty disabledEnvKeys).
  4. src/lib/onboard.ts:5902activeMessagingChannels still includes the "stopped" channel.
  5. activeMessagingChannels flows into the NEMOCLAW_MESSAGING_CHANNELS_B64 Dockerfile build arg → baked into openclaw.json in the image.
  6. src/lib/actions/sandbox/rebuild.ts:654-663preservedRegistryFields later writes disabledChannels back to the registry from the old sb snapshot, so the registry ends up correct. The image does not.

There's no runtime consumer of registry disabledChannels inside the sandbox container — openclaw.json is the source of truth at runtime — so the registry-side preservation alone is insufficient.

Metadata

Metadata

Assignees

Labels

VRDCIssues and PRs submitted by NVIDIA VRDC test team.bugSomething isn't workingenhancement: messagingEnhancements related to messing support including Slack, Telegram, Discord and WhatsApp.needs-triageNeeds human triage

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions