bolt-js: Cannot post message to DM or private group
Description
When I call app.client.chat.postMessage
with the channel id of a direct message or private group, I get the error channel_not_found
. I’m confused because my bot is able to post in channels fine. I’ve read through the api for postMessage multiple times but still don’t understand what my problem is. Thanks!
What type of issue is this? (place an x
in one of the [ ]
)
- bug
- enhancement (feature request)
- question
- documentation related
- testing related
- discussion
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 4
- Comments: 20 (9 by maintainers)
Hey folks I think I can provide some help here.
In the case of slash commands, neither a bot token nor a user token are necessary. From a security point of view, a user invoking a slash command is considered an implicit temporary grant for the app to post a message back to that conversation.
So if your app just wants to send a message to the conversation where the slash command was invoked, there’s no reason to try and get
app.client.chat.postMessage()
to work with the right token. Instead, use therespond()
function, which is passed as an argument to your listener function. Therespond()
function have be used up to 5 times within 30 minutes after the slash command was invoked. Under the hood, it uses theresponse_url
, which is described here: https://api.slack.com/interactivity/handling#message_responses. It’s also alluded to in the Bolt for JS docs , but maybe a complete example would be more helpful:For completeness, I should probably also mention that if you can come up with a response immediately (without calling some other async operation) then you should just use that as the argument for
await ack()
, as I’ve done above with “One moment please…”.Hi @mostafafarzaneh, if your app’s bot user is not in the DM, your app is unable to perform chat.postMessage API call, which is the one that
say()
uses under the hood.If your app wants to send a reply to a slash command invocation, the recommended ways are:
await ack("reply message here")
(synchronous acknowledgement response within 3 seconds)await respond("reply message here")
(respond
is a utility to easily use response_url in a payload)With these ways, your app can reply to the slash command invocation (although the app cannot respond to further messages in the DM).
@securisec unfortunately it seems that this action isn’t possible anymore with the new apps. with a legacy slack app this was possible, but as of a few months ago you have to use version 2 of slack’s oauth. it’s sort of unbelievable that the new version of slack apps leave this function out :–(
@seratch I’m just confused because I’ve played around with other bots where:
How is the above situation possible if I never explicitly invited the bot to the direct message, but just initiated their slash command?
An example of a bot that can do this is
quick-map
. If I call/quick-map canada
in a DM, it will post an image of a map of canada in the DM without any problem, and I never invited it to the DM beforehand.@mostafafarzaneh
Thanks for the feedback. Indeed, recommending
respond()
instead ofsay()
in the slash command listener code example would be more robust for any use cases. Will improve it later on.This means the situation where your app’s bot user is not a member of a direct message (say, your own direct message, direct message that consists of only human user accounts). As your app does not have the access to the DM, any Web API calls including chat.postMessage with its bot token do not work.
If the “some time” here means the one longer than 30 minutes (you can use response_url for 30 minutes), unfortunately, there is no way to do this (if a bot user is not a member of the conversation). But your app can send a quick reply message by
ack()
/respond()
. The message can include a link or button for further communications with the app somewhere outside the DM. Another way is, as I recommend below, to open a DM with the user.If your app collects all users’ xoxp- tokens with sufficient scopes, your app can access any DMs and can call Web APIs for doing something in the DM. But if you use
chat.postMessage
with the user token, the message is not from your app. Your app posts the message on behalf of the specific user. Perhaps, this is not your intention here.Our recommendation is to open a DM between a human use and your app’s bot user first. If a slash command is invoked somewhere else, your app can open a DM with the user using
conversations.open
API and post a message there to start communications with the user.Thanks for asking these questions. They should be helpful for others too! But, as this issue is already closed, please use a new issue for further questions 🙇
@seratch I am running into the same issue with a new slack app when trying to post a message that is being triggered by a slash command. I am using a bot token in this case, but am getting this message:
which seems cryptic because as we can see, proper scope is already there. IF i try to use a user token, it will post in the DM, but only as the user who installed the app which isnt the desired results.
Long story short, what can I use so that a bot can post a message in a DM as a user who invoked the command? The app is already installed in the workspace by the admin (me).
@jacklein
Could you read the following documents?
Generally speaking, using only bot tokens is suitable for most cases. Once an admin of a workspace installs the app, everyone in the workspace can use it with the same permissions and functionalities.
If your app really needs the same access a user who installed the app has, or the app may work on behalf of users, your app may use user tokens over bot tokens. In this case, the app expects every single user in the workspace to install the app. Installation here means granting user-level permissions to the app.
By the way, it seems that this question is not Bolt-specific. Is it okay to close this issue for you? Feel free to ask any other questions if you have something unclear with Bolt. 😄
@seratch If the main function of my bot is to post in the channel that the slash command is initiated from, should I consider using the user token instead of the bot token? This distinction has always confused me, and I never really understood what “bot” even means. I can of course do some more research myself, but any guidance is appreciated. Thank you!
@jacklein Ah, the app (quick-map) doesn’t have a bot user and the app uses only user tokens. If a Slack app has a user token to access a DM / private channel, the app is eligible to post a message to those conversations.