Reproducible in:
The slack_bolt version
slack_bolt==1.30.0
slack_sdk==3.45.0
Python runtime version
OS info
Steps to reproduce:
In Socket Mode, call ack() with a plain text string that starts with { but is not valid JSON.
import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
app = App(token=os.environ["SLACK_BOT_TOKEN"])
@app.command("/hello")
def hello(ack):
ack("{curly braces are fun}")
SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
- Start the app in Socket Mode.
- Run
/hello in Slack.
Expected result:
Slack receives the ack and shows the text {curly braces are fun} as the response.
Actual result:
The ack is never sent. Slack shows "failed with the error operation_timeout" and the app logs a json.JSONDecodeError.
The cause is in slack_bolt/adapter/socket_mode/internals.py (send_response) and async_internals.py (send_async_response). They decide the ack body is JSON by checking whether the text starts with {, and then call json.loads() on it without handling a parse failure:
if content_type.startswith("application/json"):
payload = json.loads(bolt_resp.body)
BoltResponse sets Content-Type: application/json for any string body that starts with {, so the same problem happens with ack("{", ...), ack("{foo"), or any text that happens to begin with that character. The non-Socket-Mode HTTP path does not have this issue because the body is sent through as-is.
I have a fix ready in #1593 that falls back to sending the string as {"text": body} whenever it cannot be parsed as a JSON object. Opening this issue at the maintainers' request so it can be tracked.
Requirements
I have read the Contributing guidelines and Code of Conduct.
Reproducible in:
The
slack_boltversionPython runtime version
OS info
Steps to reproduce:
In Socket Mode, call
ack()with a plain text string that starts with{but is not valid JSON./helloin Slack.Expected result:
Slack receives the ack and shows the text
{curly braces are fun}as the response.Actual result:
The ack is never sent. Slack shows "failed with the error operation_timeout" and the app logs a
json.JSONDecodeError.The cause is in
slack_bolt/adapter/socket_mode/internals.py(send_response) andasync_internals.py(send_async_response). They decide the ack body is JSON by checking whether the text starts with{, and then calljson.loads()on it without handling a parse failure:BoltResponsesetsContent-Type: application/jsonfor any string body that starts with{, so the same problem happens withack("{", ...),ack("{foo"), or any text that happens to begin with that character. The non-Socket-Mode HTTP path does not have this issue because the body is sent through as-is.I have a fix ready in #1593 that falls back to sending the string as
{"text": body}whenever it cannot be parsed as a JSON object. Opening this issue at the maintainers' request so it can be tracked.Requirements
I have read the Contributing guidelines and Code of Conduct.