Skip to content
🎉 Launch sale:50% off everything over $22 — automatically applied at checkout· ends Aug 2Shop the sale →
DevOps AI ToolKit
Newsletter
All guides
AI for Slack By James Joyner IV · · 8 min read Last reviewed Jul 2026

Slack Error Guide: 'cant_update_message' — Fix Edit Failures

Quick answer

Fix the Slack cant_update_message error: a bot can only edit its own messages, so match your token identity to the message author before chat.update.

  • #slack
  • #api
  • #troubleshooting
  • #errors
Free toolkit

Stuck on this Slack error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Overview

The cant_update_message error is returned by chat.update when the message exists but the authenticated token is not allowed to edit it. The core rule in Slack is that a message can only be edited by the identity that authored it: a bot can update messages it posted, and a user token can update that user’s own messages. Trying to edit a message written by a person, by a different bot, by an incoming webhook, or one posted as another identity (as_user) yields cant_update_message. It differs from message_not_found — here the message is located, but ownership fails.

Slack returns HTTP 200 with ok:false:

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

It occurs when the calling token’s identity does not match the message’s author.

Symptoms

  • chat.update finds the message (no message_not_found) but rejects the edit.
  • A bot tries to edit a message posted by a human or by an incoming webhook.
  • Editing works for messages the bot posted but fails for older ones posted under a different token/app.
  • Attempting to update a message posted with as_user:true under a user that no longer authorizes the app.
  • Trying to update an ephemeral message.

Common Root Causes

1. The message was authored by a different identity

The most common cause: the token calling chat.update is not the author. Bot tokens can only edit their own bot messages.

2. The message came from an incoming webhook

Incoming webhook messages are not owned by your bot user and cannot be edited via chat.update.

3. Human-authored messages

A bot cannot edit a person’s message. Only that user’s own token could, and only within the app’s permissions.

4. Posted as another user (as_user)

If a message was posted with as_user semantics under a user whose authorization changed, the token may no longer be able to edit it.

5. Ephemeral messages

chat.postEphemeral output is transient and cannot be updated.

Diagnostic Workflow

Step 1: Confirm the message exists (rule out message_not_found)

curl -s -G "https://slack.com/api/conversations.history" \
  --data-urlencode "channel=C0123456789" \
  --data-urlencode "latest=1720526400.001900" \
  --data-urlencode "inclusive=true" --data-urlencode "limit=1" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
  | jq '.messages[0] | {ts, user, bot_id, app_id, subtype}'
{
  "ts": "1720526400.001900",
  "user": "U04HUMAN01",
  "bot_id": null,
  "app_id": null,
  "subtype": null
}

A user id with bot_id:null means a human authored it — a bot cannot edit it.

Step 2: Identify your token’s own identity

curl -s "https://slack.com/api/auth.test" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" | jq '{user_id, bot_id}'
{
  "user_id": "U0BOTBOT01",
  "bot_id": "B08BOT0001"
}

Compare this bot_id to the message’s bot_id. They must match for chat.update to succeed.

Step 3: Reproduce the ownership failure

curl -s -X POST https://slack.com/api/chat.update \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
  -d '{"channel":"C0123456789","ts":"1720526400.001900","text":"edited"}' | jq .error
"cant_update_message"

Step 4: Verify against a message the bot DID author

# Post as the bot, then update it — this should succeed
TS=$(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":"bot msg"}' | jq -r '.ts')

curl -s -X POST https://slack.com/api/chat.update \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
  -d "{\"channel\":\"C0123456789\",\"ts\":\"$TS\",\"text\":\"bot msg (edited)\"}" | jq .ok
true

Editing the bot’s own message works, confirming the failure was ownership, not the payload.

Example Root Cause Analysis

A status bot is supposed to keep a single “current deploy” message updated. It was recently migrated from an incoming webhook to a bot token, but the message it tries to edit was posted by the old webhook:

curl -s -G "https://slack.com/api/conversations.history" \
  --data-urlencode "channel=C0123456789" --data-urlencode "latest=1720526400.001900" \
  --data-urlencode "inclusive=true" --data-urlencode "limit=1" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" | jq '.messages[0] | {bot_id, app_id, subtype}'
{
  "bot_id": "B01WEBHOOK9",
  "app_id": "A01WEBHOOK9",
  "subtype": "bot_message"
}

The message’s bot_id (B01WEBHOOK9) belongs to the retired webhook integration, not the new bot (B08BOT0001), so the edit is refused. The fix is to have the new bot POST its own status message and update that one going forward:

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":"deploy: in progress"}' | jq -r '.ts'
1720526799.004100

From then on the bot updates the message it authored, and cant_update_message disappears.

Prevention Best Practices

  • Only update messages your bot authored; store the ts of messages the bot itself posts and edit those.
  • Compare auth.test.bot_id to the message’s bot_id before attempting chat.update if ownership is ever uncertain.
  • Migrate off incoming webhooks to a bot token if you need editable messages — webhook posts are not editable.
  • Never attempt to edit human-authored messages from a bot; design the workflow to post a new bot message instead.
  • Track chat.postEphemeral output separately; it cannot be updated or deleted.
  • For ad-hoc triage, the free incident assistant can compare authoring bot_id to your token identity. See more in Slack guides.

Quick Command Reference

# Who is this token?
curl -s "https://slack.com/api/auth.test" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" | jq '{user_id, bot_id}'

# Who authored the message?
curl -s -G "https://slack.com/api/conversations.history" \
  --data-urlencode "channel=C0123456789" --data-urlencode "latest=TS" \
  --data-urlencode "inclusive=true" --data-urlencode "limit=1" \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" | jq '.messages[0] | {user, bot_id, app_id}'

# Update a message the bot authored
curl -s -X POST https://slack.com/api/chat.update \
  -H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
  -d '{"channel":"C0123456789","ts":"TS","text":"edited"}' | jq .ok

Conclusion

cant_update_message means the message exists but the calling token is not its author. The usual root causes:

  1. The message was posted by a different bot or app.
  2. It came from an incoming webhook (not editable).
  3. It was authored by a human.
  4. It was posted as_user under an identity that changed.
  5. It is an ephemeral message.

Only edit messages your bot posted: match your auth.test identity to the message’s bot_id, and if you inherited an unowned message, post a fresh one and update that instead.

Free download · 368-page PDF

Fixed it? Get 500 Slack & DevOps AI prompts — free

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.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

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.