Slack Error: 'hash_conflict' — Cause, Fix, and Troubleshooting Guide
Fix the Slack hash_conflict error: views.update sent a stale view hash. Always pass the hash from the most recent view and handle concurrent updates.
- #slack
- #api
- #troubleshooting
- #errors
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
hash_conflict is returned by views.update (and views.publish) when the hash you supplied is stale. Slack uses the hash as an optimistic-concurrency token: if the view changed since you read that hash, the update is rejected to prevent clobbering a newer state.
{
"ok": false,
"error": "hash_conflict"
}
Symptoms
- Modal updates fail intermittently, usually when the user interacts quickly.
- Two code paths update the same view and one fails.
- The first update after opening works; a second update with the old hash fails.
Common Root Causes
1. Reusing a stale hash
You cached the hash from views.open and kept using it after the view already changed via a subsequent update or user interaction.
2. Concurrent updates racing
Two handlers (e.g. a timer and a user action) update the same view; the slower one carries an out-of-date hash.
3. Updating from the wrong event’s hash
Each interaction payload carries the latest view.hash; using a hash from an earlier payload conflicts.
How to diagnose
Every interaction payload includes the current view and its hash — log it:
# From a block_actions / view_submission payload:
{
"view": {
"id": "V0VIEW00001",
"hash": "1700000000.AbCdEf",
"type": "modal"
}
}
Then reproduce an update with a deliberately old hash:
curl -s -X POST https://slack.com/api/views.update \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"view_id":"V0VIEW00001","hash":"1699999999.OLDHASH","view":{"type":"modal","title":{"type":"plain_text","text":"Setup"},"blocks":[]}}'
{"ok": false, "error": "hash_conflict"}
Fixes
- Always send the freshest
hash— take it from the most recent interaction payload’sview.hash, not a cached copy. - Or omit
hashentirely and update byview_idonly when you don’t need concurrency protection (last-write-wins). - Serialise updates to a given view (per-view lock/queue) so two handlers don’t race.
- On conflict, re-read and retry: catch
hash_conflict, use the latest hash from the newest event, and re-apply your change.
What to watch out for
- Omitting
hashtrades safety for simplicity — you lose protection against overwriting a newer state, which can drop a user’s in-flight input. - Prefer updating by
view_idfor the top view; usepush/updatesemantics deliberately in multi-step wizards. hash_conflictis expected under contention — treat it as a retry-with-fresh-hash signal, not a hard failure.
Related
- Slack Error: ‘expired_trigger_id’
- Slack Error: ‘invalid_payload’
- Slack modals and interactive components for ops tooling
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?
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.