I am working with slack command (python code is running behind this), it works fine, but this gives error
This slash command experienced a problem: 'Timeout was reached' (error detail provided only to team owning command).
How to avoid this ?
I am working with slack command (python code is running behind this), it works fine, but this gives error
This slash command experienced a problem: 'Timeout was reached' (error detail provided only to team owning command).
How to avoid this ?
After dealing with this issue myself and having my Flask app hosted on Heroku I found that the simplest solution was to use threading. I followed the example from here: https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xi-email-support
All the slow heavy work is performed by the
backgroundworker()
function. My slack command points tohttps://myappaddress.com/appmethodaddress
where thereceptionist()
function takes theresponse_url
of the received Slack message and passes it alongside any other optional data to thebackgroundworker()
. As the process is now split it simply returns the"working on your request"
message to your Slack channel pretty much instantly and upon completionbackgroundworker()
sends the second message"your task is complete"
.I too was facing this error frequently:
I was writing a Slack slash-command "bot" on AWS Lambda that sometimes needed to perform slow operations (invoking other external APIs etc). The Lambda function would take greater than 3 seconds in some cases causing the
Timeout was reached
error from Slack.I found @rcoup's excellent answer here and applied it in the context of AWS Lambda. The error doesn't appear any more.
I did this with two separate Lambda functions. One is a "dispatcher" or "receptionist" that greets the incoming Slack slash command with a "200 OK" and returns the simple "Ok, got that" type of message to the user. The other is the actual "worker" Lambda function that starts the long-ish operation asynchronously and posts the result of that operation to the Slack
response_url
later.This is the dispatcher/receptionist Lambda function:
As you can see from the above, I didn't invoke the worker Lambda Function directly from the dispatcher (though this is possible). I chose to use AWS SNS to publish a message that the worker receives and processes.
Based on this StackOverflow answer, this is the better approach as it's non-blocking (asynchronous) and scalable. Also it was easier to use SNS to decouple the two functions in the context of AWS Lambda, direct invocation is trickier for this use-case.
Finally, here's how I consume the SNS event in my worker Lambda Function:
According to the Slack slash command documentation, you need to respond within 3000ms (three seconds). If your command takes longer then you get the
Timeout was reached
error. Your code obviously won't stop running, but the user won't get any response to their command.Three seconds is fine for a quick thing where your command has instant access to data, but might not be long enough if you're calling out to external APIs or doing something complicated. If you do need to take longer, then see the Delayed responses and multiple responses section of the documentation:
200
response immediately, maybe something along the lines of{'text': 'ok, got that'}
response_url
parameter. Make aPOST
request to that URL with your follow-up message:Content-type
needs to beapplication/json
{'text': 'all done :)'}
According to the docs, "you can respond to a user commands up to 5 times within 30 minutes of the user's invocation".
Create thread to do major part of work and return response to slack. You can also return a response when thread will complete.