Skip to content

GetThreadContext returns None in user_message handler #1452

@jczhong84

Description

@jczhong84

Reproducible in:

slack_bolt==1.27.0
slack_sdk==3.40.1

The slack_bolt version

slack_bolt==1.27.0

Python runtime version

Python 3.12

OS info

Linux

Steps to reproduce:

  1. Create an Assistant with either the default store or a custom AssistantThreadContextStore
  2. Save thread context in thread_started using save_thread_context()
  3. Call get_thread_context() in user_message handler
from slack_bolt import App
from slack_bolt import Assistant, Say

assistant = Assistant()  # default store or custom — same result

@assistant.thread_started
def handle_thread_started(say, save_thread_context, payload):
    thread_context = payload["assistant_thread"]["context"]
    save_thread_context(thread_context)  # ✅ works, store.save() is called
    say("Hi!")

@assistant.thread_context_changed
def handle_context_changed(save_thread_context, payload):
    new_context = payload["assistant_thread"]["context"]
    save_thread_context(new_context)  # ✅ works

@assistant.user_message
def handle_user_message(say, get_thread_context):
    ctx = get_thread_context()  # ❌ always None, store.find() never called
    print(ctx)

app = App(token="xoxb-...", signing_secret="...")
app.use(assistant)
app.start(port=3000)

Expected result:

get_thread_context() should call store.find() and return the previously saved context (e.g., {"channel_id": "C0ADEEWTZPB", "team_id": "TU8CUBAPP", ...}).

Actual result:

get_thread_context() always returns None. The store's find() method is never invoked.

Root cause

In GetThreadContext.call(), the code checks if "assistant_thread" in self.payload before checking for channel/thread_ts:

if "assistant_thread" in self.payload:
    context = self.payload["assistant_thread"].get("context", {})
    if context.get("channel_id"):
        self._thread_context = AssistantThreadContext(context)
    self.thread_context_loaded = True

elif self.payload.get("channel") and self.payload.get("thread_ts"):
    self._thread_context = self.thread_context_store.find(
        channel_id=self.payload["channel"],
        thread_ts=self.payload["thread_ts"],
    )

In assistant_thread_started events, payload["assistant_thread"] contains a full context dict — this works fine.

However, in user_message events, payload["assistant_thread"] only contains an action_token:

{
  "assistant_thread": {
    "action_token": "10647138185092.960436384805.afce3599..."
  }
}

Because the key "assistant_thread" exists, the if branch is entered. There's no context inside, so _thread_context stays None. Then thread_context_loaded is set to True, and the elif branch that calls store.find() is never reached.

Requirements

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions