binary-husky/gpt_academic · error · RuntimeError

获取Slack消息失败。

Error message

获取Slack消息失败。

What it means

A Slack API failure while fetching the bot's replies: get_slack_messages() calls conversations_history and wraps SlackApiError / KeyError in RuntimeError('获取Slack消息失败。'). SlackApiError means the Slack HTTP API returned an error payload (bad token, missing scope, invalid channel); KeyError means the response JSON lacked the expected 'messages' field.

Source

Thrown at request_llms/bridge_stackclaude.py:67

                raise Exception("Channel not found.")

            resp = await self.chat_postMessage(channel=self.CHANNEL_ID, text=text)
            self.LAST_TS = resp["ts"]

        async def get_slack_messages(self):
            try:
                # TODO:暂时不支持历史消息,因为在同一个频道里存在多人使用时历史消息渗透问题
                resp = await self.conversations_history(
                    channel=self.CHANNEL_ID, oldest=self.LAST_TS, limit=1
                )
                msg = [
                    msg
                    for msg in resp["messages"]
                    if msg.get("user") == get_conf("SLACK_CLAUDE_BOT_ID")
                ]
                return msg
            except (SlackApiError, KeyError) as e:
                raise RuntimeError(f"获取Slack消息失败。")

        async def get_reply(self):
            while True:
                slack_msgs = await self.get_slack_messages()
                if len(slack_msgs) == 0:
                    await asyncio.sleep(0.5)
                    continue

                msg = slack_msgs[-1]
                if msg["text"].endswith("Typing…_"):
                    yield False, msg["text"]
                else:
                    yield True, msg["text"]
                    break

except:
    pass

View on GitHub (pinned to d6bde0fa54)

Solutions

  1. Verify SLACK_CLAUDE_USER_TOKEN is valid: curl -H 'Authorization: Bearer <token>' https://slack.com/api/auth.test
  2. Add the required read scope (im:history / channels:history) to the token and reinstall the app
  3. Check you are not rate-limited: the get_reply loop polls every 0.5s, back off if Slack returns 429
  4. Catch SlackApiError and log e.response['error'] to see the exact Slack code (invalid_auth, channel_not_found, missing_scope, ratelimited)

Example fix

# before
except (SlackApiError, KeyError) as e:
    raise RuntimeError(f"获取Slack消息失败。")

# after
except SlackApiError as e:
    raise RuntimeError(f"获取Slack消息失败: {e.response['error']}") from e
except KeyError as e:
    raise RuntimeError(f"获取Slack消息失败: unexpected payload, missing {e}") from e
Defensive patterns

Strategy: try-catch

Validate before calling

from slack.errors import SlackApiError
test = await client.conversations_history(channel=client.CHANNEL_ID, limit=1)
assert 'messages' in test, 'unexpected Slack payload shape'

Try / catch

try:
    msgs = await client.get_slack_messages()
except RuntimeError:
    logger.exception('conversations_history failed; token/scopes/rate-limit?')
    await asyncio.sleep(2)  # back off, loop continues
except Exception:
    raise

Prevention

When it happens

Trigger: conversations_history(channel=CHANNEL_ID, oldest=LAST_TS, limit=1) failing inside the get_reply() polling loop of request_llms/bridge_stackclaude.py:67 — e.g. expired/revoked SLACK_CLAUDE_USER_TOKEN, token without channels:history scope, CHANNEL_ID pointing to an inaccessible channel, or Slack returning an error shape without resp['messages'].

Common situations: User token rotated or revoked after setup; bot removed from workspace; missing history scope on the legacy token; Slack rate limit (429) during the 0.5s polling loop; CHANNEL_ID stale after workspace migration.

Related errors


AI-assisted analysis of binary-husky/gpt_academic@d6bde0fa54 (2026-08-14). Data as JSON: /api/errors/ec614ded5c50482e. Report an issue: GitHub.