Slack not_in_channel Error: Join, Invite, or chat:write.public
not_in_channel means the bot is not a member of the channel you posted or read from. Public channel: conversations.join or chat:write.public. Private channel: /invite the app. Every response here came from a real app.
On this page
Slack returns not_in_channel when your bot tries to post to or read from a channel it is not a member of. For a public channel there are two fixes: have the bot join with conversations.join (scope channels:join), or add the chat:write.public scope so it can post without joining. For a private channel, a person in the channel has to add the app, for example with /invite @YourApp or with conversations.invite and their own user token, as in our add-to-channel tests. A private channel the bot is not in usually does not return not_in_channel at all; it returns channel_not_found. We reproduced every case below on 29 September 2026 with a test bot in a one-person workspace. The same membership rule decides whether a bot hears an @mention at all; what the person sees in that case is in Slack bot not responding.
What we sent and what Slack answered
The bot had only chat:write. We created a public channel, a private channel and an archived channel, and did not add the bot to any of them.
| Call | Channel | Response |
|---|---|---|
chat.postMessage | public, bot not a member | not_in_channel |
chat.postMessage | public, by name #w1-lab-public | not_in_channel |
chat.postMessage | public, by name without # | not_in_channel |
chat.postMessage | private, bot not a member | channel_not_found |
chat.postMessage | archived, bot not a member | not_in_channel |
chat.postMessage | archived, bot is a member | is_archived |
conversations.history | public, bot not a member | not_in_channel |
reactions.add | public, bot not a member | not_in_channel |
Each came back as HTTP 200 with a body like this:
{"ok": false, "error": "not_in_channel"}
Two rows surprise people. A channel name works as well as an ID for public channels: Slack found the channel and then refused because the bot was not in it. And the archived channel returns not_in_channel until the bot is a member; only then do you see the real reason, is_archived.
Fix 1: join the public channel with conversations.join
Add the channels:join bot scope, reinstall the app, then call:
curl -s https://slack.com/api/conversations.join \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-d channel=C0C4RQXFPAT
Our bot got {"ok": true, ...} with the channel object, a "joined #w1-lab-public" line appeared in the channel, and the next chat.postMessage returned ok: true. Joining also fixed conversations.history and reactions.add, which the next fix does not. Once the bot is in, reading every page of the channel history is a cursor loop.
conversations.join works only on public channels. On our private channel it returned channel_not_found, and on the archived one is_archived.
Fix 2: post without joining, with chat:write.public
Add the chat:write.public scope and reinstall. The bot can then post to any public channel without being a member. Our first post after the reinstall went through, then the bot joined, then it posted again:
This scope covers posting only. In the same state, conversations.history and reactions.add on that channel still returned not_in_channel. It also does nothing for private channels: chat.postMessage to our private channel still returned channel_not_found.
Use it when a bot posts alerts to many public channels and never needs to read them. Otherwise, join.
Never appear "away" on Slack again
Cloud-based. No downloads. Works 24/7 even when your laptop is off.
Fix 3: invite the app to a private channel
A bot cannot add itself to a private channel. Someone in the channel types /invite @ and the app's name. Slack's picker marks the app Not in channel:
After the invite, the post that had failed with channel_not_found returned ok: true, and conversations.history worked too. When we removed the bot with conversations.kick, the next post failed with channel_not_found again.
If a person @-mentions the app in a private channel it is not in, Slack offers the same fix to that person only:
The message with the mention is still posted; the prompt is only visible to the sender.
If you still get not_in_channel
- • Check the token. If your code has two tokens, the call may use the one whose bot was never invited.
auth.testreturns theuser_idof the bot the token belongs to; that user must be in the channel's member list. - • Check the channel. A webhook URL is tied to the channel picked at install, but
chat.postMessageuses whateverchannelyou pass. Copy the ID from the channel's details, at the bottom of the About tab. - • For GitHub Actions, the invite step is the one people skip. The workflow setup is in how to send a Slack message from GitHub Actions.
The related errors each have their own page: missing_scope when the token lacks a permission, and channel_not_found when Slack cannot see the channel at all.
FAQ
Why do I get channel_not_found instead of not_in_channel on a private channel? Slack hides private channels from apps that are not members, so to the bot the channel does not exist. Invite the app and the error goes away.
Does chat:write.public need a reinstall? Yes, like any scope change. Until the app is reinstalled, the token keeps its old scopes.
Can an incoming webhook hit not_in_channel? We never saw it from one. A webhook posts only to the channel chosen when it was created, and none of our 450 test posts to a webhook returned this error. Its errors are covered in Slack webhook curl example.
Stop Jiggling Your Mouse.
Join hundreds of remote workers who never worry about their Slack status. Set it up once, stay green forever.
Related Articles
How to See All Your DMs in Slack, Including the Hidden Ones
The DMs tab lists your direct messages with people. App DMs, Slackbot and DMs with deleted accounts sit elsewhere. We compared the tab with the full list the Slack API returned.
Slack Images Not Showing? 5 Causes We Reproduced
We uploaded images to a Slack test channel and then switched each image setting off, ran /collapse, and posted from a bot that was not in the channel. Five causes, each reproduced.
How to Message Yourself on Slack (and What It Notifies)
Your own name under Direct messages opens a private DM with yourself. We sent it a note, a file, a scheduled message and a reminder, and checked which ones raised a badge.