openclaw - ✅(Solved) Fix Cron delivery to Slack failing with 'Unsupported channel: slack' [1 pull requests, 3 comments, 4 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#53769Fetched 2026-04-08 01:23:36
View on GitHub
Comments
3
Participants
4
Timeline
7
Reactions
0
Author
Timeline (top)
commented ×3cross-referenced ×3subscribed ×1

Error Message

Cron run output:

{
  "status": "error",
  "error": "Unsupported channel: slack",
  "deliveryStatus": "unknown"
}

No relevant errors in ~/.openclaw/logs/gateway.log related to delivery failure.

Fix Action

Workaround

Direct Slack API calls work fine:

curl -X POST https://slack.com/api/chat.postMessage \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"channel":"U03QT833TC7","text":"Test"}'

Returns {"ok":true} successfully.

PR fix notes

PR #53944: fix(gateway): pin channel registry at startup to survive registry swaps

Description (problem / solution / changelog)

Summary

  • Problem: getChannelPlugin() returns undefined after a runtime registry swap, causing Channel is unavailable: <channel> errors on all outbound message delivery — the message tool, subagent completion announces, and cron delivery. The channel is known (isKnownChannel() passes via the hardcoded CHANNEL_IDS array) but the plugin backing it is gone from the live registry.
  • Why it matters: On a production Slack gateway, upgrading to 2026.3.22 introduced 38 Channel is unavailable: slack errors/day and 72 subagent announce failures/day — up from zero on the previous version. Reproduced and confirmed still present on 2026.3.23-2. Users see dropped replies and undelivered subagent results with no feedback. The issue affects all channels (Slack, Telegram, WhatsApp, Discord) — see Related Issues below.
  • Root cause: Non-primary loadOpenClawPlugins() calls (config-schema reads, provider registry lookups, maybeBootstrapChannelPlugin fallback) can replace the active plugin registry via setActivePluginRegistry(). The replacement registry may have a different channel plugin set — or none at all — because it was built with different loader options. getChannelPlugin() in channels/plugins/registry.ts resolves against the live requireActivePluginRegistry(), so it immediately loses access to the channels that were present at gateway boot.
  • What changed: Added a pinned channel registry (3 new functions in runtime.ts) mirroring the existing pinActivePluginHttpRouteRegistry pattern. The channel registry is pinned at gateway startup in server-runtime-state.ts and released on shutdown. resolveCachedChannelPlugins() now reads from requireActivePluginChannelRegistry() instead of requireActivePluginRegistry(), so channel resolution is immune to mid-flight registry swaps.
  • What did NOT change (scope boundary): No changes to plugin loading, config reload, channel setup/teardown, message delivery pipeline, or the outbound channel resolution fallback chain. The resolveOutboundChannelPlugin bootstrap path still works as before — it just no longer needs to fire because the pinned registry already has the channels.

🤖 AI-assisted

  • Marked as AI-assisted
  • Degree of testing: fully tested (7 new tests + 613 existing channel/outbound/plugin tests pass)
  • I understand what the code does
  • Bot review conversations will be resolved

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Related #48790 (underlying tracking issue for channel registry instability)
  • Related #53117 (Telegram: Channel is unavailable regression in 2026.3.22)
  • Related #53879 (Telegram: file upload fails with Channel is unavailable in 2026.3.23-2)
  • Related #53769 (Slack: cron delivery failing with Unsupported channel: slack)
  • Related #53204 (subagent announce retry blocks agent session for ~6 min on channel errors)
  • Related #38055 (subagent completion announce permanently lost when channel unavailable)
  • Related #38457 (Slack Socket Mode: channel_id not passed to tool context)

User-visible / Behavior Changes

Channel plugins registered at gateway startup are no longer evicted by subsequent plugin registry swaps. The message tool, subagent announces, cron delivery, and all other outbound paths that resolve channels via getChannelPlugin() will consistently find the channel plugin as long as the gateway is running.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Linux (GCE, Debian 12) / macOS
  • Runtime: Node 22
  • OpenClaw: 2026.3.22 through 2026.3.23-2 (confirmed on both)
  • Channel: Slack (Socket Mode), also affects Telegram, WhatsApp, Discord

Steps

  1. Start a gateway with Slack (or any channel) enabled
  2. Trigger a non-primary plugin registry load (e.g., Control UI fetches config schema, or a subagent spawns and bootstraps plugins)
  3. Send a message to the agent, or have a subagent complete and try to announce

Expected

  • Channel plugin is found, message is delivered

Actual (before fix)

  • getChannelPlugin("slack") returns undefined
  • [tools] message failed: Channel is unavailable: slack
  • Subagent completion direct announce failed: Error: Unknown channel: slack
  • After 3 retries with exponential backoff, the announce is permanently dropped

Evidence from production

Before (2026.3.22, no pin) — 7-day daily error count:

Mon: 0    Thu: 0    Sun: 20
Tue: 0    Fri: 0    Mon: 38
Wed: 0    Sat: 0
# First error appeared Sunday 15:43 UTC — immediately after 2026.3.22 upgrade

Log pattern (cascading announce failures):

12:35:38 [ws] res ✗ agent errorCode=UNAVAILABLE errorMessage=Error: Unknown channel: slack
12:35:38 Subagent completion direct announce failed for run <id>: Error: Unknown channel: slack
12:35:40 Subagent completion direct announce failed for run <id>: Error: Unknown channel: slack  # retry 2
12:35:44 Subagent completion direct announce failed for run <id>: Error: Unknown channel: slack  # retry 3
# → permanently lost, parent session never notified

Affected session types:

  • slack:channel:* — channel thread replies
  • slack:direct:* — DM replies
  • subagent:* — subagent completion announces
  • openai:* — MCP/API sessions attempting Slack delivery

Tests

7 new tests covering pin/release/swap lifecycle:

✓ returns the active registry when not pinned
✓ preserves pinned channel registry across setActivePluginRegistry calls
✓ updates channel registry on swap when not pinned
✓ release restores live-tracking behavior
✓ release is a no-op when the pinned registry does not match
✓ requireActivePluginChannelRegistry creates a registry when none exists
✓ resetPluginRuntimeStateForTest clears channel pin

Full test run: 7 new + 613 existing channel/outbound/plugin tests pass.

Co-Authored: Mário Sousa (@mariosousa-finn)

Changed files

  • src/channels/plugins/registry.ts (modified, +2/-2)
  • src/gateway/server-runtime-state.ts (modified, +18/-1)
  • src/gateway/server.impl.ts (modified, +574/-503)
  • src/gateway/server.minimal-channel-pin.test.ts (added, +57/-0)
  • src/plugins/runtime.channel-pin.test.ts (added, +118/-0)
  • src/plugins/runtime.ts (modified, +55/-0)

Code Example

"channels": {
  "slack": {
    "mode": "socket",
    "enabled": true,
    "botToken": "[REDACTED]",
    "appToken": "[REDACTED]",
    "dmPolicy": "pairing",
    "dm": {"enabled": true},
    "channels": {"C0ADJGJR55G": {"allow": true}},
    "nativeStreaming": true,
    "streaming": "partial"
  }
}

---

2026-03-24T10:14:27.987-05:00 [health-monitor] started

---

{
  "name": "Test Job",
  "schedule": {"kind": "cron", "expr": "*/5 * * * *"},
  "sessionTarget": "isolated",
  "payload": {
    "kind": "agentTurn",
    "message": "Test message"
  },
  "delivery": {
    "mode": "announce",
    "channel": "slack",
    "to": "user:U03QT833TC7"
  }
}

---

curl -X POST https://slack.com/api/chat.postMessage \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"channel":"U03QT833TC7","text":"Test"}'

---

{
  "status": "error",
  "error": "Unsupported channel: slack",
  "deliveryStatus": "unknown"
}
RAW_BUFFERClick to expand / collapse

Cron delivery to Slack failing with "Unsupported channel: slack"

Environment

  • Version: OpenClaw 2026.3.22 (e7d11f6)
  • Platform: macOS (Darwin 25.2.0, arm64)
  • Installation: Git source (/Users/aiden/clawdbot/)
  • Gateway started: 2026-03-24 10:13:44 CDT

Problem

Cron jobs configured with delivery: {mode: "announce", channel: "slack", to: "user:U03QT833TC7"} are failing with error: "Unsupported channel: slack"

This affects both:

  • sessionTarget: "isolated" + payload.kind: "agentTurn" jobs
  • sessionTarget: "main" + payload.kind: "systemEvent" jobs

Configuration

Slack is properly configured and working:

"channels": {
  "slack": {
    "mode": "socket",
    "enabled": true,
    "botToken": "[REDACTED]",
    "appToken": "[REDACTED]",
    "dmPolicy": "pairing",
    "dm": {"enabled": true},
    "channels": {"C0ADJGJR55G": {"allow": true}},
    "nativeStreaming": true,
    "streaming": "partial"
  }
}

Gateway logs show Slack connecting successfully:

2026-03-24T10:14:27.987-05:00 [health-monitor] started

Reproduction

Create a cron job with Slack delivery:

{
  "name": "Test Job",
  "schedule": {"kind": "cron", "expr": "*/5 * * * *"},
  "sessionTarget": "isolated",
  "payload": {
    "kind": "agentTurn",
    "message": "Test message"
  },
  "delivery": {
    "mode": "announce",
    "channel": "slack",
    "to": "user:U03QT833TC7"
  }
}

Result: Job completes but delivery fails with "Unsupported channel: slack"

Expected Behavior

Cron jobs should successfully deliver messages to Slack DMs when configured with proper delivery settings.

Actual Behavior

  • Job execution succeeds
  • Message is generated
  • Delivery fails with "Unsupported channel: slack"
  • deliveryStatus shows "unknown"

Workaround

Direct Slack API calls work fine:

curl -X POST https://slack.com/api/chat.postMessage \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"channel":"U03QT833TC7","text":"Test"}'

Returns {"ok":true} successfully.

Additional Context

  • Multiple cron jobs affected (morning reminders, AI digest, daily drip)
  • Issue appeared after updating job from sessionTarget: "main" to sessionTarget: "isolated"
  • But reverting to sessionTarget: "main" also fails with same error
  • Gateway restart did not resolve issue

Logs

Cron run output:

{
  "status": "error",
  "error": "Unsupported channel: slack",
  "deliveryStatus": "unknown"
}

No relevant errors in ~/.openclaw/logs/gateway.log related to delivery failure.

extent analysis

Fix Plan

The fix involves updating the delivery configuration in the cron job to use the correct channel type.

  • Update the cron job configuration to use the socket mode for Slack delivery:
"delivery": {
  "mode": "socket",
  "channel": "slack",
  "to": "user:U03QT833TC7"
}
  • Alternatively, you can also try using the webhook mode if socket mode is not supported:
"delivery": {
  "mode": "webhook",
  "channel": "slack",
  "to": "user:U03QT833TC7"
}
  • If the issue persists, verify that the Slack configuration is correct and the bot token and app token are valid.

Verification

To verify that the fix worked, create a new cron job with the updated delivery configuration and check the delivery status. The job should complete successfully and the message should be delivered to the Slack DM.

  • Check the cron job output for a successful delivery status:
{
  "status": "success",
  "deliveryStatus": "delivered"
}
  • Verify that the message is received in the Slack DM.

Extra Tips

  • Make sure to restart the gateway after updating the configuration to ensure the changes take effect.
  • If you are still experiencing issues, try checking the Slack API documentation to ensure that the bot token and app token are being used correctly.
  • Consider adding error handling to the cron job to catch and log any delivery errors for further debugging.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Cron delivery to Slack failing with 'Unsupported channel: slack' [1 pull requests, 3 comments, 4 participants]