Slack API Error Guide: 'missing_scope' Token Lacks Required Permission
Fix the Slack API missing_scope error: diagnose absent OAuth scopes, bot-vs-user scope confusion, stale tokens after reinstall, and the needed vs provided fields.
- #slack
- #troubleshooting
- #errors
- #scopes
Overview
The missing_scope error means the token is valid and authenticates fine, but it was not granted the OAuth scope the endpoint requires. Slack tells you exactly which scope is missing and which scopes the token currently has, in the needed and provided fields. This is a permission gap, not a credential failure — the fix is to add the scope and reinstall the app so a new token is issued.
You will see this in the JSON body, with the diagnostic fields included:
{
"ok": false,
"error": "missing_scope",
"needed": "chat:write",
"provided": "channels:read,users:read"
}
It occurs the first time you call an endpoint whose scope you never requested, or after Slack tightens an endpoint’s scope requirement.
Symptoms
- A specific endpoint returns
ok: falsewitherror: missing_scope. - The response includes
needed(the scope to add) andprovided(what you have). auth.testsucceeds, proving the token itself is valid.- The call started failing after an endpoint or SDK change.
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channel":"C0123456789","text":"hello"}'
{
"ok": false,
"error": "missing_scope",
"needed": "chat:write",
"provided": "channels:read"
}
Common Root Causes
1. The required scope was never requested
The app’s manifest/OAuth config never listed the scope the endpoint needs. needed names it directly.
curl -s -X POST https://slack.com/api/conversations.create \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"new-channel"}'
{
"ok": false,
"error": "missing_scope",
"needed": "channels:manage",
"provided": "chat:write,channels:read"
}
Add channels:manage to the bot scopes.
2. Bot vs. user scope confusion
Some endpoints require a user token scope, not a bot scope. chat:write on a bot token will not satisfy a user-only endpoint, and vice versa.
curl -s "https://slack.com/api/auth.test" \
-H "Authorization: Bearer $SLACK_USER_TOKEN"
{
"ok": true,
"user_id": "U0REALUSER",
"bot_id": null
}
If bot_id is null this is a user token; ensure the scope is added under User Token Scopes.
3. The token is stale — scope added but app not reinstalled
Adding a scope in the dashboard does nothing until the app is reinstalled and a fresh token is issued. The old token still reports the old provided set.
curl -s "https://slack.com/api/apps.permissions.scopes.list" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
"ok": true,
"scopes": {
"bot": ["channels:read", "chat:write"]
}
}
If the newly added scope is absent here, you are still using the pre-reinstall token.
4. A granular endpoint needs an extra companion scope
Some actions require two scopes (e.g. reading a file needs files:read; writing needs files:write). Having one is not enough.
curl -s "https://slack.com/api/files.info?file=F0123456789" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
"ok": false,
"error": "missing_scope",
"needed": "files:read",
"provided": "files:write"
}
5. Reading a conversation type without its read scope
Listing or reading private channels, DMs, or MPIMs needs groups:read, im:read, or mpim:read respectively.
curl -s "https://slack.com/api/conversations.history?channel=D0123456789" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
"ok": false,
"error": "missing_scope",
"needed": "im:history",
"provided": "channels:history"
}
6. An admin/enterprise endpoint needs an admin scope
admin.* endpoints require admin.* scopes and an org-level install — ordinary bot scopes never satisfy them.
curl -s "https://slack.com/api/admin.conversations.search" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
{
"ok": false,
"error": "missing_scope",
"needed": "admin.conversations:read",
"provided": "channels:read,chat:write"
}
Diagnostic Workflow
Step 1: Read the needed and provided fields
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channel":"C0123456789","text":"hi"}'
needed is the scope to add; provided is what the current token actually has. This is usually the whole answer.
Step 2: Confirm whether it is a bot or user scope
curl -s "https://slack.com/api/auth.test" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
A non-null bot_id means a bot token (add under Bot Token Scopes); null means a user token (User Token Scopes).
Step 3: List the scopes the token actually carries
curl -s "https://slack.com/api/apps.permissions.scopes.list" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
Confirm the needed scope is genuinely absent and not just a stale-token illusion.
Step 4: Add the scope and reinstall
In the app’s OAuth & Permissions page, add the needed scope under the correct token type, then reinstall the app to the workspace. Reinstalling is mandatory — it mints the new token.
Step 5: Update the secret and retry with the new token
# After reinstall, pull the new token, then:
curl -s "https://slack.com/api/apps.permissions.scopes.list" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channel":"C0123456789","text":"hi"}'
{
"ok": true,
"channel": "C0123456789",
"ts": "1718900000.000200"
}
Example Root Cause Analysis
An app that posts CI results suddenly logs missing_scope after a code change added a reaction to each message:
curl -s -X POST https://slack.com/api/reactions.add \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channel":"C0123456789","timestamp":"1718900000.000200","name":"white_check_mark"}'
{"ok": false, "error": "missing_scope", "needed": "reactions:write", "provided": "chat:write,channels:read"}
The post itself works (chat:write is present), but reactions.add needs reactions:write, which was never requested. Confirming with the scope list:
curl -s "https://slack.com/api/apps.permissions.scopes.list" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
{"ok": true, "scopes": {"bot": ["channels:read", "chat:write"]}}
Fix: add reactions:write to the bot scopes, reinstall the app, pull the new token, and retry. The reaction is added successfully.
Prevention Best Practices
- Treat the
neededfield as authoritative — add exactly that scope rather than guessing related ones. - Always reinstall the app after changing scopes; the dashboard change has no effect on existing tokens until reinstall.
- Keep an app manifest in version control listing every scope, so new endpoints are reviewed against granted permissions before deploy.
- Verify whether an endpoint wants a bot or user scope; mixing the two is a frequent cause of repeated
missing_scope. - Pair read/write companion scopes (
files:read/files:write,*:history/*:read) when an endpoint touches both. - For ad-hoc triage, the free incident assistant can map a
neededscope to the exact dashboard change required. See more in Slack guides.
Quick Command Reference
# Reproduce and read needed/provided
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d '{"channel":"C0123456789","text":"hi"}'
# Bot token or user token?
curl -s "https://slack.com/api/auth.test" -H "Authorization: Bearer $SLACK_BOT_TOKEN"
# What scopes does the token actually have?
curl -s "https://slack.com/api/apps.permissions.scopes.list" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN"
# Retry after adding scope and reinstalling
curl -s -X POST https://slack.com/api/reactions.add \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d '{"channel":"C0123456789","timestamp":"1718900000.000200","name":"tada"}'
Conclusion
missing_scope is the friendliest Slack error — it names the fix in the needed field. The usual root causes:
- The required scope was never requested in the app config.
- A bot scope used where a user scope (or vice versa) is required.
- A scope added in the dashboard but the app never reinstalled (stale token).
- A companion scope missing for a read/write pair.
- A conversation-type read scope absent for private channels or DMs.
- An
admin.*endpoint needing an org-level admin scope.
Read needed vs provided, add the scope under the correct token type, reinstall, and re-pull the token — the permission gap closes the moment a fresh token carries the scope.
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.