Describe your issue here.
x in one of the [ ])x in each of the [ ])I cannot use Interactive URL to response the form error for view_submission

I write the api for interactive url in Lambda, then I set the interactive url and submit the form. I always receive this error on the view modal:
We had some trouble connecting. Try again?
The response for view_submission event that is requested to my server
{
response_action: "errors",
errors: {
"restaurant-name": "You may not select a due date in the past"
}
}
I don't know the error details, and I don't know how I can fix it. It's so hopeless :(
How about making sure if your Lambda function really received the requests by checking CloudWatch logs?
I'm not sure what your situation is but there are several possible patterns:
@seratch, I mean when I make an action on Slack, Slack makes a request by using the interactive url I provided in the app's settings. My server receive the request from Slack (through interactive-endpoint) and send back to Slack the response like this:
{
response_action: "errors",
errors: {
"restaurant-name": "You may not select a due date in the past"
}
}
With status code: 200
But I always receive:
We had some trouble connecting. Try again?
But when I try to send the empty response with 200 OK, it close the modal view with no error
I see. Does your modal have the restaurant-name?
Just to be clear, your handler is returning the object you've shown above, right? And as @seratch mentioned, "restaurant-name" is the block_id of the block which contains the input element, right?
Let's also try to make sure it isn't timing out. Can you follow the instructions for debugging, and let us know what you see in the logs?
@seratch My modal has a block with id restaurant-name. Is it right?
@aoberoi Here is the log
@slack/interactive-messages:adapter instantiated +0ms
@slack/interactive-messages:http-handler request received - method: POST, path: / +0ms
@slack/interactive-messages:http-handler Parsing raw request +1ms
@slack/interactive-messages:http-handler request signing verification success +3ms
@slack/interactive-messages:adapter dispatching to handler +2s
Here is my modal
{
"type": "modal",
"callback_id": "create-form",
"title": {
"type": "plain_text",
"text": "Tạo thực đơn",
"emoji": true
},
"submit": {
"type": "plain_text",
"text": "Tạo menu",
"emoji": true
},
"close": {
"type": "plain_text",
"text": "Hủy",
"emoji": true
},
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Vui lòng *điền đầy đủ* thông tin bên dưới để tạo thực đơn:"
}
},
{
"type": "input",
"block_id": "restaurant-name",
"element": {
"type": "plain_text_input",
"placeholder": {
"type": "plain_text",
"text": "Quán Cơm 321"
}
},
"label": {
"type": "plain_text",
"text": "Tên nhà hàng/quán ăn",
"emoji": true
}
},
{
"type": "input",
"block_id": "restaurant-menu",
"element": {
"type": "plain_text_input",
"multiline": true,
"placeholder": {
"type": "plain_text",
"text": "Tên món ăn 1|Đơn giá\nTên món ăn 2|Đơn giá\nTên món ăn 3|Đơn giá"
}
},
"label": {
"type": "plain_text",
"text": "Danh sách món ăn",
"emoji": true
}
}
]
}
This is the viewSubmission handler. I am using Express
slackInteractions.viewSubmission("create-form", payload => {
return Promise.resolve({
response_action: "errors",
errors: { "restaurant-name": "You may not select a due date in the past" }
});
});
Now It works like a charm when I move from Lambda to native Nodejs express server.

Okay that’s great news. We’ve narrowed the problem down to usage with AWS Lambda. I haven’t used this package on Lambda before but you might find the information here helpful: https://github.com/slackapi/node-slack-sdk/issues/896
I'm having random lambda issues also. This is a very vague untested theory:
I _think_ the issue is thinking about the lambda as a server that can just keep running and processing async callbacks. I believe slack operates by both allowing responses to the initial request, but also posting of new messages to a specific response_url after returning a blank 200 to the initial request.
As Lambda kills the running instance as soon as you return from it. there's no continuing on and then making another call to the response_url as a traditional server would do. I think perhaps we need to trigger a new lambda somehow to do that. I'm not sure it's possible with interactive-messages
Again this is just a hunch.
Has anyone ever confirmed this?
I think @dannyshaw is right.
Anyone come up with a workaround?
(FYI: I'm actually working in Python, but the behavior / error / cloud is the same... That's why I think it's Slack and and not a language or SDK per se.)
+1 on the above, getting the following error
slack.errors.SlackApiError: The request to the Slack API failed.
The server responded with: {'ok': False, 'error': 'invalid_arguments', 'response_metadata': {'messages': ['[ERROR] must provide an object [json-pointer:/view]']}}
with a payload of
{
"type": "modal",
"response_action": "errors",
"errors": {
"block_test": "lol"
},
"title": {
"type": "plain_text",
"text": "Notification settings",
"emoji": true
},
"submit": {
"type": "plain_text",
"text": "Submit",
"emoji": true
},
"close": {
"type": "plain_text",
"text": "Cancel",
"emoji": true
},
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*<fakelink.toUrl.com|PR Strategy 2019> posts into <fakelink.toChannel.com|#public-relations>*\n\nSelect which notifications to send:"
}
},
{
"type": "input",
"block_id": "block_test"
"element": {
"type": "plain_text_input"
},
"label": {
"type": "plain_text",
"text": "Label",
"emoji": true
}
}
]
}
@lemonbakeoff
Yes, as @dannyshaw mentioned, when running apps on AWS Lambda (or any other FaaS), developers should be aware of the possibility of termination of app containers once apps return an HTTP response to Slack. https://github.com/slackapi/bolt/issues/361 and https://github.com/slackapi/bolt/issues/395 are related to this topic and illustrate how we recognize this issue.
The available solutions are:
1) have a queue to store messages from Slack and run another lambda function that takes and processes those messages asynchronously (the function can use response_url).
2) use Bolt for JS's processBeforeResponse: true option and await say, respond, etc. (I know you're not using Bolt but Bolt for this use case is much easier)
const app = new App({
signingSecret: process.env.SLACK_SIGNING_SECRET,
token: process.env.SLACK_BOT_TOKEN,
processBeforeResponse: true,
});
app.command("/hellol", async ({ respond, ack }) => {
await respond("What's up?"); // posts a message using response_url
await ack(); // returns 200 OK after response_url call completion
});
@an-dev
The JSON structure your app sends is invalid. You can use Block Kit Builder (Modal Preview) as a handy way to validate your payloads this way.
The valid one should be like this.
Regarding the errors response, it is not supposed to be merged into the view. Your app sends only the following JSON data as an HTTP response to a view_submissiontyped request from Slack. Refer to the official document for details: https://api.slack.com/surfaces/modals/using#displaying_errors
{
"response_action": "errors",
"errors": {
"block_test": "lol"
}
}
@seratch Thanks for your insight. I assumed the error response was to be merged with the existing modal template as the documentation isn't explicit about it being separate.
@seratch regarding your Bolt example :
app.command("/hellol", async ({ respond, ack }) => {
await respond("What's up?"); // posts a message using response_url
await ack(); // returns 200 OK after response_url call completion
});
Does it still mean the logic done before ack has to to be done under 3 seconds ?
@gterras yes it does. It is a limitation of the current design but most use cases should be able to complete within that timeframe. Are you running into issues with it?
I get occasional ack fails on Cloudrun which is expected to be sometimes slow (cold start, instance creation etc). This or any random network error can delay the response. This lead to a very unpredictable and confusing UX unfortunately (can click two times the same button, grey triangle popping etc)
I fear that getting a response consistently under 3 seconds (actually less ?) is not possible for anyone who built an app following traditional Slack guidelines about events response, even if the processing logic is simple. There are too much factors and the risk is too high. The queue system seems the only reasonable things to do then, but what does processBeforeResponse actually do ?
FYI after discussion with my cloud team we concluded that by nature a Slack app is incompatible with FaaS core concepts (can't guarantee a cold start + request processing in less than 3s). Moving the app to AppEngine seems much more reasonable (same range of prices, container always up) and allow repositionning the ack at the top of listeners like a standard Slack app.
@gterras processBeforeResponse allows your logic to run before ack is called. We found that calling ack, lambda would terminate because a response was sent and it wouldn't get to processing the logic. With processBeforeResponse, this was fixed.
IMO an always up solution is a better for slack apps, but we still want to support folks who want to use lambda (even though it has the limitations which you correctly mentioned).
I'm sure the team already provided answers (at least responses) to all the questions and comments (the original question about modals and general questions about cold-starts) in this issue.
Let me share some additional thoughts on the processBeforeResponse option. As already mentioned, the option is not a solution for 3 second timeout errors and/or general cold-start issues on FaaS. The option just guarantees all the code in a listener surely completes. For dealing with timeouts (due to long operations and cold-starts), you need to be a bit more creative.
Just for your information, we started offering lazy listener functions in Bolt for Python as an experimental feature. To know what it is, refer to the document and an example code. The feature is yet another way to realize the concept I proposed at https://github.com/slackapi/bolt-js/issues/361. It runs an asynchronous operation in another invocation of the same Lambda function with the same args (body, context, say, respond, and so on). The only difference is the async function is unable to call ack() method. This feature should be greatly helpful for building meaningful Slack apps on FaaS (or on-demand container services like Cloud Run). Developers can use this feature in addition to process_before_response: True option.
We haven't decided to implement the same feature in Bolt for JS yet in the short term. The concept may have some conflict with Bolt for JS's fundamental design concept - a listener is a sequential chain of middleware. So, at this point, our general recommendation is to go with some solution that enables you to store messages in a queue (say, SQS) plus to run another function that subscribes the queue asynchronously.
Thanks for writing in and sharing your thoughts here! If you would like to discuss the FaaS topic further, please feel free to create a discussion issue in bolt-js project like https://github.com/slackapi/bolt-js/issues/361.
Most helpful comment
I'm having random lambda issues also. This is a very vague untested theory:
I _think_ the issue is thinking about the lambda as a server that can just keep running and processing async callbacks. I believe slack operates by both allowing responses to the initial request, but also posting of new messages to a specific
response_urlafter returning a blank 200 to the initial request.As Lambda kills the running instance as soon as you return from it. there's no continuing on and then making another call to the
response_urlas a traditional server would do. I think perhaps we need to trigger a new lambda somehow to do that. I'm not sure it's possible withinteractive-messagesAgain this is just a hunch.