Skip to content

extract_team_id crashes with TypeError when payload["user"] is a string (e.g. member_joined_channel events) #1447

@dbermuehler

Description

@dbermuehler

Reproducible in:

The slack_bolt version

slack-bolt==1.27.0
slack-sdk==3.39.0

Python runtime version

Python 3.14.0

OS info

ProductName:    macOS
ProductVersion: 26.3
BuildVersion:   25D125
Darwin Kernel Version 25.3.0: Wed Jan 28 20:53:05 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6020

Steps to reproduce:

  1. Register a member_joined_channel listener in a Slack Bolt app:
@app.event("member_joined_channel")
def handle_channel_join(event, client, say):
    say("Hello!")
  1. Add the bot to any Slack channel.

  2. Observe the incoming event payload — Slack sends "user" as a plain string (the user ID):

{
  "type": "member_joined_channel",
  "user": "U0123456789",
  "channel": "C0123456789",
  "team": "T0123456789"
}

Expected result:

The listener is invoked normally.

Actual result:

The request crashes before the listener is reached, with:

TypeError: string indices must be integers, not 'str'

File "slack_bolt/adapter/aws_lambda/handler.py", line 87, in to_bolt_request
    return BoltRequest(
File "slack_bolt/request/request.py", line 69, in __init__
    self.context = build_context(BoltContext(context if context else {}), self.body)
File "slack_bolt/request/internals.py", line 276, in build_context
    team_id = extract_team_id(body)
File "slack_bolt/request/internals.py", line 116, in extract_team_id
    return payload["user"]["team_id"]

Root cause

extract_team_id in slack_bolt/request/internals.py assumes payload["user"] is always a dict:

if payload.get("user") is not None:
    return payload["user"]["team_id"]

But member_joined_channel sends "user" as a plain string (the user ID). Accessing "U0123456789"["team_id"] raises the TypeError.

The same function already handles payload["team"] correctly with an isinstance check:

if payload.get("team") is not None:
    team = payload.get("team")
    if isinstance(team, str):
        return team
    elif team and "id" in team:
        return team.get("id")

The same guard is missing for payload["user"]. This pattern (subscribing to member_joined_channel and checking if the joined user is the bot) is what maintainers recommend in #710, so users following that guidance will hit this bug.

Metadata

Metadata

Assignees

No one assigned

    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