Skip to content

[Bug]: Slack streaming: false (boolean) resolves to "partial" instead of "off" #25990

@jaden-clovervnd

Description

@jaden-clovervnd

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

  1. Set channels.slack.streaming: false in openclaw.json
  2. Send a message to the bot via Slack
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions