Skip to content

[Bug]: Slack thread context silently lost when thread_ts resolution fails (~10% of threads) #12389

@fayrose

Description

@fayrose

[Bug]: Slack thread context intermittently lost (~10% of threads)

Summary

Thread replies intermittently lose all conversation context. The agent correctly responds to the first message in a thread, then on the user's follow-up reply (still in the same thread), the agent has complete amnesia—no memory of the thread at all.

This affects roughly 1 in 10 threads.

Bug Pattern

  1. User sends message in channel
  2. Bot replies correctly (creates thread)
  3. User replies in thread (~1 minute later)
  4. Bot response has amnesia—no knowledge of prior conversation

Root Cause: Unknown

Investigated & Ruled Out

1. Silent failure in
esolveThreadTsFromHistory()

Originally thought to be the cause. However, this would affect message 1, not message 2. By the time the user replies in-thread, hread_ts is already present in the Slack event payload—no resolution needed.

2. Race condition in initSessionState()
Found a real race condition where concurrent messages can create duplicate sessions. However, with ~1 minute gaps between messages, this is unlikely to trigger for the observed bug pattern.

3. Thread_ts normalization issues
Investigated and ruled out—normalization is applied consistently.

Still Investigating

The actual cause remains unknown. Possibilities include:

  • History not being saved after first turn
  • Session invalidation between turns
  • Subtle session key mismatch on lookup
  • Something in the Slack adapter's message routing

Environment

  • OpenClaw version: 2026.2.6-3
  • OS: Windows 11 (also reported on macOS)
  • Channel: Slack (Socket Mode)
  • Config:
    eplyToMode: "all", default thread settings

Real Bugs Found (Worth Fixing Regardless)

1. Silent failure in

esolveThreadTsFromHistory()

Even if this isn't the root cause of this bug, silent failures are bad:

javascript catch (err) { // SILENT FAILURE - only logs in verbose mode if (shouldLogVerbose()) logVerbose(\slack inbound: failed to resolve thread_ts...\); return; // Returns undefined silently }

Recommendation: Log at warning level, not just verbose.

2. Race condition in initSessionState()

Concurrent messages can create duplicate sessions, orphaning conversation history. Should use atomic session initialization.

3. Consider conversations.replies over conversations.history

conversations.replies is the correct API for resolving thread context—it's stateless and works for all threads, not just bot-initiated ones.

Investigation Details

Full analysis with code paths, message flow diagrams, and file references:
https://gist.github.com/fayrose/4f922f71b32c410d81c9f626ddeadc57

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstaleMarked as stale due to inactivity

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions