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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions