-
-
Notifications
You must be signed in to change notification settings - Fork 54.4k
Description
Summary
channels.slack.streaming: false (boolean) is silently treated as "partial" instead of "off", causing duplicate messages in Slack.
Root Cause
In resolveSlackStreamingMode():
function resolveSlackStreamingMode(params = {}) {
const parsedStreaming = parseStreamingMode(params.streaming);
if (parsedStreaming) return parsedStreaming;
const legacyStreamMode = parseSlackLegacyDraftStreamMode(params.streamMode);
if (legacyStreamMode) return mapSlackLegacyDraftStreamModeToStreaming(legacyStreamMode);
if (typeof params.streaming === "boolean") return "partial"; // ← BUG
return "partial";
}parseStreamingMode() calls normalizeStreamingMode() which returns null for non-string values. Then the typeof === "boolean" check catches both true AND false, returning "partial" for both.
streaming: true→"partial"✅ (intended legacy migration)streaming: false→"partial"❌ (should be"off")streaming: "off"→"off"✅ (works correctly)
Impact
Users who set streaming: false (a natural way to disable streaming) get preview streaming enabled, causing:
- Duplicate messages: a draft/preview message (marked
(edited)) + a final message with identical content - Particularly noticeable with short replies
Steps to Reproduce
- Set
channels.slack.streaming: falseinopenclaw.json - Send a message to the bot via Slack
- Observe two identical messages — one with
(edited)tag, one without
Expected Fix
if (typeof params.streaming === "boolean") return params.streaming ? "partial" : "off";Or handle it in normalizeStreamingMode:
function normalizeStreamingMode(value) {
if (value === false) return "off";
if (value === true) return "partial";
if (typeof value !== "string") return null;
return value.trim().toLowerCase() || null;
}Workaround
Use the string value instead of boolean:
{ "channels": { "slack": { "streaming": "off" } } }Environment
- OpenClaw version: 2026.2.23
- OS: macOS (Darwin 25.2.0 arm64)
- Channel: Slack (socket mode)
Note
The CHANGELOG mentions: "Legacy keys (streamMode, Slack boolean streaming) are still read and migrated by openclaw doctor --fix" — but doctor --fix does not appear to catch this false → "partial" case. The resolveSlackNativeStreaming function has the same issue:
function resolveSlackNativeStreaming(params = {}) {
if (typeof params.nativeStreaming === "boolean") return params.nativeStreaming; // ✅ correct
if (typeof params.streaming === "boolean") return params.streaming; // ✅ correct for nativeStreaming
return true;
}resolveSlackNativeStreaming correctly handles booleans, but resolveSlackStreamingMode does not.