Repository navigation
Description
[bug] Slack Socket Mode crashes on boot with invalid_auth — appToken missing from baked openclaw.json; token resolution also appears broken
Summary
NemoClaw v0.0.20 onboarding with the Slack messaging channel selected produces a
sandbox that cannot connect to Slack. On every boot the gateway crashes with
an unhandled promise rejection:
[openclaw] Unhandled promise rejection: Error: An API error occurred: invalid_auth
at platformErrorFromResult (.../@slack/web-api/src/errors.ts:119:5)
at WebClient.apiCall (.../@slack/web-api/src/WebClient.ts:405:36)
The crash takes the entire gateway down (and with it, the dashboard at
:18789), so the sandbox is unusable whenever Slack credentials are present.
Environment
- NemoClaw: v0.0.20
- Host: macOS 26.3.1 on Apple M4 Mac Mini (16 GB unified memory)
- Runtime: Docker Desktop
- Inference provider:
ollama-local/gemma4:e4b - Messaging channel:
slack(Socket Mode) - Policy tier: Balanced +
slackpreset applied - Install path: interactive
nemoclaw onboard, with later
nemoclaw nemo rebuildandnemoclaw onboard --non-interactive --resume --recreate-sandboxiterations while debugging.
Two issues that together cause the crash
Issue 1 — generated openclaw.json is missing appToken
The Dockerfile generates the baked openclaw.json from
NEMOCLAW_MESSAGING_CHANNELS_B64. The Python block at Dockerfile:245:
_token_keys = {'discord': 'token', 'telegram': 'botToken', 'slack': 'botToken'}
_env_keys = {'discord': 'DISCORD_BOT_TOKEN',
'telegram': 'TELEGRAM_BOT_TOKEN',
'slack': 'SLACK_BOT_TOKEN'}
_ch_cfg = {ch: {'accounts': {'default': {
_token_keys[ch]: f'openshell:resolve:env:{_env_keys[ch]}',
'enabled': True, ...
}}} for ch in msg_channels if ch in _token_keys}Result: the baked /sandbox/.openclaw/openclaw.json has only botToken for
Slack. No appToken. @slack/bolt Socket Mode cannot initialize without an
App-Level Token, so apps.connections.open fails immediately.
Observed baked config:
"channels": {
"slack": {
"accounts": {
"default": {
"botToken": "openshell:resolve:env:SLACK_BOT_TOKEN",
"enabled": true
// NOTE: appToken is missing
}
}
}
}Issue 2 — openshell:resolve:env:* placeholders never resolve to real tokens
Even after patching the Dockerfile to also emit
"appToken": "openshell:resolve:env:SLACK_APP_TOKEN", the Slack SDK still
receives invalid_auth.
Inside the sandbox:
$ env | grep SLACK
SLACK_BOT_TOKEN=openshell:resolve:env:SLACK_BOT_TOKEN
SLACK_APP_TOKEN=openshell:resolve:env:SLACK_APP_TOKENi.e. the literal marker strings, not the real tokens. For Brave, the same
marker appears in openclaw.json but the sandbox env has the real value
(because openshell sandbox create is called with
--env BRAVE_API_KEY=BSA... directly). For Slack there is no equivalent — the
openshell sandbox create command records:
--provider nemo-slack-bridge --provider nemo-slack-app -- env CHAT_UI_URL=... BRAVE_API_KEY=BSA...
No SLACK_BOT_TOKEN=... or SLACK_APP_TOKEN=... injected. The
nemo-slack-bridge and nemo-slack-app OpenShell providers are registered
with credential keys, but setting them via:
openshell provider update nemo-slack-bridge --credential SLACK_BOT_TOKEN=xoxb-...
openshell provider update nemo-slack-app --credential SLACK_APP_TOKEN=xapp-...
does not cause the L7 proxy to substitute the placeholder strings. Requests
reach slack.com with Authorization: Bearer openshell:resolve:env:SLACK_BOT_TOKEN
(inferred from the invalid_auth response; the real tokens are verified valid
via curl from the host).
Gateway container env is also empty of slack tokens:
$ docker exec openshell-cluster-nemoclaw env | grep -i slack
# (no output)So neither the sandbox env, nor the proxy container env, nor the openclaw.json
itself contains the real token values, despite nemoclaw credentials list
showing both tokens stored.
Reproduction
- Fresh install:
curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash - Onboarding:
nemoclaw onboard- Inference: Install Ollama /
gemma4:e4b - Messaging: Slack only, paste valid
xoxb-andxapp-tokens - Policy tier: Balanced; verify
slackpreset is toggled on
- Inference: Install Ollama /
- Wait for the sandbox to come up.
- Observe (inside sandbox):
cat /sandbox/.openclaw/openclaw.json | jq '.channels.slack' # → only botToken, no appToken env | grep SLACK # → openshell:resolve:env:... literals, not real tokens - Tail the sandbox gateway log — crash loop on
invalid_authwithin seconds of
[slack] [default] starting provider.
Expected behavior
openclaw.jsonincludesappTokenwhen Slack is selected, so Socket Mode
has what it needs.openshell:resolve:env:*placeholders are resolved (either at build time
when tokens are baked, at sandbox-create env injection time like Brave, or
at egress-proxy rewrite time) so thatAuthorization: Bearer <real-token>
reaches Slack.- Dashboard stays up on boot regardless of whether Slack auth succeeds
(a single channel failure should not crash the entire gateway — the
unhandled promise rejection should be caught and the channel marked
unavailable in the UI).
Local patch I applied (partial fix)
Edited Dockerfile line 247 to append an appToken spread for slack:
- **({'dmPolicy': ...} if ... else {})}}}
+ **({'dmPolicy': ...} if ... else {}), **({'appToken': 'openshell:resolve:env:SLACK_APP_TOKEN'} if ch == 'slack' else {})}}}After rebuild, openclaw.json contains both botToken and appToken, but
the runtime invalid_auth persists because Issue 2 is unresolved — the proxy
or sandbox env never receives the real token values.
Additional notes / related papercuts surfaced while debugging
-
Race condition on sandbox boot. Policy presets are applied AFTER
openshell sandbox create, so on first boot the sandbox egress denies
slack.com:443and the gateway crashes withFailed to establish tunnel to slack.com:443 ... HTTP/1.1 403 Forbidden. By the time theslackpreset
lands, the process has exited. A subsequent manual restart of the gateway
does reach Slack, but only to hit Issue 2. -
Rebuild refuses when sandbox is already dead.
nemoclaw nemo rebuild
exits with "Sandbox 'nemo' is not running. Cannot back up state. Start it
first or recreate withnemoclaw onboard --recreate-sandbox." This is
accurate messaging but traps users whose sandbox crashed on the Slack bug
above — they now need the slower onboard-recreate path to recover. -
credentials listhas noaddcounterpart. Once a credential is
missing, the only documented way to re-enter it is to re-run
nemoclaw onboard, which forces another rebuild. Anemoclaw credentials set KEY(reading from stdin silently) would help a lot — especially since
the current onboarding flow re-pulls the Docker validation image and risks
the macOS keychain lock issue ([WSL2] NemoClaw sandbox cannot reach Windows-hosted Ollama — local inference path blocked (relates to #305, #315, #246) #336 is adjacent) over SSH sessions. -
Dashboard exits with gateway crash. Because the dashboard is served by
the same node process as the Slack provider, one unhandled promise
rejection takes the whole UI down. Users then can't even see the failure
state in the dashboard — the port is unresponsive.
Happy to contribute a PR for Issue 1 (the Dockerfile appToken fix is a
one-liner). Issue 2 likely needs someone with visibility into the
openshell:resolve:env:* resolution path to point me at the right surface.
References
- NemoClaw: https://github.com/NVIDIA/NemoClaw (v0.0.20)
- OpenClaw slack plugin schema location in-sandbox:
/usr/local/lib/node_modules/openclaw/dist/zod-schema.providers-core-*.js
(showsappToken: SecretInputSchema.optional().register(sensitive)) - Adjacent issue on SSH/sandbox network reach: [WSL2] NemoClaw sandbox cannot reach Windows-hosted Ollama — local inference path blocked (relates to #305, #315, #246) #336
Activity
fix(policy): restore L4 tunnel for WebSocket hosts via tls: skip
wscurran commentedon Apr 20, 2026
✨ Thanks for submitting this issue that identifies a problem with the Slack Socket Mode crashing on boot. The steps to reproduce and environment information you provided will help us investigate this further.
fix(policy): restore L4 tunnel for WebSocket hosts via tls: skip (#2098)
fix(dockerfile): emit appToken for slack in baked openclaw.json (#2146)
fix(onboard): inject Slack tokens as --env in sandbox create (NVIDIA#…
fix(sandbox): address CodeRabbit feedback on Slack token scrub (NVIDI…
fix(onboard): prompt for SLACK_APP_TOKEN during interactive channel s…
fix(sandbox): resolve Slack Socket Mode invalid_auth startup crash (#…
docs: prep for v0.0.22 (#2209)
feat(channels): replace Slack token carve-out with Bolt-shape rewriter (
feat(channels): replace Slack token carve-out with Bolt-shape rewriter (