Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Slack By James Joyner IV · · 9 min read

Slack API Error Guide: 'channel_not_found' Invalid or Inaccessible Channel

Fix the Slack API channel_not_found error: diagnose wrong channel IDs, cross-workspace tokens, deleted channels, name-vs-ID confusion, and DM access with curl.

  • #slack
  • #troubleshooting
  • #errors
  • #channels

Overview

The channel_not_found error means Slack cannot resolve the channel value you passed to a conversation that this token is allowed to see. Either the ID is malformed, the channel was deleted, the token belongs to a different workspace, or the bot has no visibility into a private conversation. Unlike not_in_channel (the channel exists but the bot is not a member), channel_not_found means the API does not return the channel at all for this token.

You will see this in the JSON body:

{
    "ok": false,
    "error": "channel_not_found"
}

It occurs on almost any conversation endpoint — chat.postMessage, conversations.history, conversations.info, conversations.invite — whenever the supplied channel reference does not map to a conversation visible to the calling token.

Symptoms

  • chat.postMessage returns ok: false with error: channel_not_found.
  • conversations.info for the same ID also returns channel_not_found.
  • The same ID works with a different app’s token but not yours.
  • A channel that worked yesterday now returns the error (deleted/archived).
curl -s "https://slack.com/api/conversations.info?channel=C0XXXXXXXXX" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
    "ok": false,
    "error": "channel_not_found"
}

Common Root Causes

1. The channel ID is wrong or malformed

A typo, truncated ID, or a value with stray whitespace will not resolve. Valid IDs start with C (public/private channel), G (legacy private group), or D (DM).

curl -s "https://slack.com/api/conversations.list?types=public_channel,private_channel&limit=200" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" | head -30
{
    "ok": true,
    "channels": [
        {"id": "C0123456789", "name": "deploys"},
        {"id": "C0198765432", "name": "alerts"}
    ]
}

If your target ID is not in this list, it does not exist for this token.

2. The token belongs to a different workspace

Channel IDs are workspace-scoped. A token from workspace B cannot see workspace A’s channels, even if the ID is valid there.

curl -s "https://slack.com/api/auth.test" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
    "ok": true,
    "team_id": "T0AAAAAAA",
    "team": "ACME Prod",
    "user_id": "U0BOTBOT01"
}

If team_id is not the workspace that owns the channel, you will always get channel_not_found.

3. The channel was deleted or its ID changed

A deleted channel disappears entirely. Archived channels still resolve via conversations.info, but a truly deleted one returns channel_not_found.

curl -s "https://slack.com/api/conversations.list?types=public_channel&exclude_archived=false&limit=200" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" | grep C0XXXXXXXXX
(no output)

No match in the full (including archived) list means the channel is gone.

4. A channel name was passed instead of an ID

Passing #deploys or deploys instead of C0123456789 does not resolve on most modern endpoints, which require the ID.

curl -s -X POST https://slack.com/api/chat.postMessage \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"channel":"#deploys","text":"hi"}'
{
    "ok": false,
    "error": "channel_not_found"
}

Resolve the name to an ID with conversations.list first.

5. A private channel the bot cannot see

Private channels are invisible to a bot that is not a member, so conversations.info returns channel_not_found rather than revealing the channel’s existence.

curl -s "https://slack.com/api/conversations.list?types=private_channel&limit=200" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
    "ok": true,
    "channels": []
}

An empty private list (when private channels do exist) means the bot has not been invited to any.

6. Missing the scope to read that conversation type

Without channels:read / groups:read / im:read, the corresponding conversations are invisible and resolve as not found.

curl -s "https://slack.com/api/conversations.info?channel=C0123456789" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
    "ok": false,
    "error": "missing_scope",
    "needed": "channels:read",
    "provided": "chat:write"
}

A bare channel_not_found alongside missing read scopes points at the scope gap.

Diagnostic Workflow

Step 1: Confirm which workspace the token is in

curl -s "https://slack.com/api/auth.test" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN"

Match team_id/team against the workspace that owns the channel. A mismatch is the answer.

Step 2: List conversations and search for the ID

curl -s "https://slack.com/api/conversations.list?types=public_channel,private_channel&exclude_archived=false&limit=1000" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  | grep -o '"id":"C[0-9A-Z]*","name":"[^"]*"'

If your target ID appears, it exists for this token; if not, it is wrong, deleted, or invisible.

Step 3: Probe the specific ID directly

curl -s "https://slack.com/api/conversations.info?channel=C0XXXXXXXXX" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN"

channel_not_found here, with a valid token, narrows it to deleted / wrong-workspace / private-invisible.

Step 4: Resolve a name to a canonical ID

curl -s "https://slack.com/api/conversations.list?types=public_channel&limit=1000" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  | grep -o '"id":"C[0-9A-Z]*","name":"deploys"'
"id":"C0123456789","name":"deploys"

Use that id everywhere instead of the name.

Step 5: Verify scopes and retry

curl -s "https://slack.com/api/auth.test" -H "Authorization: Bearer $SLACK_BOT_TOKEN"
# After fixing ID/scope:
curl -s "https://slack.com/api/conversations.info?channel=C0123456789" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
    "ok": true,
    "channel": {"id": "C0123456789", "name": "deploys"}
}

Example Root Cause Analysis

A staging notifier that worked for months suddenly logs channel_not_found for every post. The token still authenticates:

curl -s "https://slack.com/api/auth.test" -H "Authorization: Bearer $SLACK_BOT_TOKEN"
{"ok": true, "team_id": "T0AAAAAAA", "team": "ACME Prod", "user_id": "U0BOTBOT01"}

The token is valid and in the right workspace. Searching the full conversation list, including archived, for the hard-coded ID returns nothing:

curl -s "https://slack.com/api/conversations.list?exclude_archived=false&limit=1000" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" | grep C0DELETED99
(no output)

Someone deleted the old #staging-notify channel and created a new one with a fresh ID. The hard-coded ID no longer exists.

Fix: resolve the new channel by name and update the config:

curl -s "https://slack.com/api/conversations.list?limit=1000" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  | grep -o '"id":"C[0-9A-Z]*","name":"staging-notify"'
"id":"C09NEWCHAN1","name":"staging-notify"

Point the notifier at C09NEWCHAN1 and posts succeed again.

Prevention Best Practices

  • Resolve channel names to IDs at deploy time and store the C… ID; never hard-code a #name into API calls.
  • Validate the token’s team_id matches the target workspace during startup, so cross-workspace token swaps fail loudly.
  • Cache conversations.list and refresh it on channel_deleted / channel_rename events so stale IDs are caught immediately.
  • Grant the read scopes (channels:read, groups:read) that match the conversation types you address, so visibility never silently drops.
  • Distinguish channel_not_found (resolve/visibility problem) from not_in_channel (membership problem) in your error handling — the fixes differ.
  • For ad-hoc triage, the free incident assistant can separate a deleted-channel failure from a wrong-workspace token. See more in Slack guides.

Quick Command Reference

# Which workspace is this token in?
curl -s "https://slack.com/api/auth.test" -H "Authorization: Bearer $SLACK_BOT_TOKEN"

# Does the ID exist (including archived)?
curl -s "https://slack.com/api/conversations.list?exclude_archived=false&limit=1000" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" | grep C0XXXXXXXXX

# Probe a specific channel
curl -s "https://slack.com/api/conversations.info?channel=C0XXXXXXXXX" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN"

# Resolve a name to an ID
curl -s "https://slack.com/api/conversations.list?limit=1000" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  | grep -o '"id":"C[0-9A-Z]*","name":"deploys"'

Conclusion

channel_not_found means the channel reference does not resolve to a conversation this token can see. The usual root causes:

  1. A wrong, truncated, or whitespace-padded channel ID.
  2. A token from a different workspace than the channel’s.
  3. A channel that was deleted (its ID no longer exists).
  4. A #name passed where the API expects a C… ID.
  5. A private channel the bot has never been invited to.
  6. Missing read scopes for that conversation type.

Confirm the token’s workspace, search the conversation list for the ID, and resolve names to canonical IDs — the channel reference is the single variable to nail down.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.