Grafana Error Guide: 'Someone else has updated this dashboard' — Save Version Conflict
Fix 'Someone else has updated this dashboard' save conflicts in Grafana — resolve version mismatches from concurrent edits, provisioning overwrites, and stale UIDs, and save changes safely.
- #grafana
- #troubleshooting
- #errors
- #dashboards
Overview
Grafana uses optimistic concurrency for dashboard saves. Every dashboard has an integer version. When you open a dashboard the UI holds the version you loaded; on save it sends that number back. If the stored version is now higher — because someone (or something) saved in between — Grafana rejects the write with HTTP 412 Precondition Failed rather than silently clobbering their work.
The literal errors you will see:
Someone else has updated this dashboard. Would you like to save anyway?
{"message":"The dashboard has been changed by someone else","status":"version-mismatch"}
status=412 msg="Failed to save dashboard" error="version mismatch"
It occurs whenever the on-disk/DB version outran the copy in your browser: a coworker saved, a provisioning reload rewrote it, or you had the same dashboard open in two tabs.
Symptoms
- The save dialog shows “Someone else has updated this dashboard” with a “Save anyway” button.
- API
POST /api/dashboards/dbreturns412withversion-mismatch. - Edits appear to “revert” moments after saving — something else keeps rewriting the dashboard.
- Two browser tabs on the same dashboard fight each other.
curl -s -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/dashboards/uid/<uid> | jq '.dashboard.version, .meta.provisioned'
47
true
Common Root Causes
1. Concurrent human edits
Two people (or two tabs) edit the same dashboard. The first save bumps the version; the second still holds the old number and is rejected.
2. Provisioning keeps overwriting UI edits
A file-provisioned dashboard is re-applied on Grafana’s provisioning interval or reload. Your UI save lands, then provisioning rewrites it from disk, bumping the version out from under the next save.
grep -R "path:" /etc/grafana/provisioning/dashboards/*.yaml
apiVersion: 1
providers:
- name: 'default'
updateIntervalSeconds: 30
allowUiUpdates: false
options:
path: /var/lib/grafana/dashboards
With allowUiUpdates: false, UI edits to provisioned dashboards are not meant to persist.
3. Automation / Terraform racing the UI
A grafana_dashboard Terraform resource or a CI job posts the dashboard JSON while a human is editing it.
4. Stale version sent by an API client
A script that caches the dashboard model and posts overwrite: false with an old version gets a mismatch on the second run.
Diagnostic Workflow
Step 1: Read the current stored version and provisioning flag
curl -s -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/dashboards/uid/<uid> \
| jq '{version: .dashboard.version, provisioned: .meta.provisioned, updated: .meta.updated, updatedBy: .meta.updatedBy}'
Step 2: Check the version history for who/what saved
curl -s -H "Authorization: Bearer $TOKEN" \
"http://localhost:3000/api/dashboards/uid/<uid>/versions?limit=5" \
| jq '.[] | {version, created, createdBy, message}'
{"version":47,"createdBy":"provisioning","message":""}
{"version":46,"createdBy":"jsmith","message":"tweak thresholds"}
createdBy: provisioning between two human saves is the smoking gun.
Step 3: Confirm provisioning behavior
grep -R "allowUiUpdates\|updateIntervalSeconds" /etc/grafana/provisioning/dashboards/
journalctl -u grafana-server --no-pager | grep -i provisioning | tail
Step 4: Save correctly via API
Fetch the current version immediately before posting:
VER=$(curl -s -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/dashboards/uid/<uid> | jq '.dashboard.version')
# include that version, or set overwrite:true to force
curl -s -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-X POST http://localhost:3000/api/dashboards/db \
-d "{\"dashboard\": $DASHBOARD_JSON, \"overwrite\": true, \"message\": \"ci sync\"}"
Example Root Cause Analysis
An engineer edits thresholds on “Prod Overview”, clicks Save, sees “Someone else has updated this dashboard”, and hits Save anyway. Ten minutes later the thresholds are back to the old values. Version history:
{"version":51,"createdBy":"provisioning"}
{"version":50,"createdBy":"engineer","message":"raise cpu threshold"}
{"version":49,"createdBy":"provisioning"}
The dashboard is file-provisioned with allowUiUpdates: false and updateIntervalSeconds: 30. Every 30s Grafana re-reads the JSON from disk and rewrites the dashboard, so any UI edit is transient and every subsequent UI save races the provisioner.
Fix: treat the file as the source of truth. The engineer edits the JSON in the Git repo that feeds /var/lib/grafana/dashboards, opens a PR, and lets the pipeline redeploy. UI edits stop being lost because they’re no longer used. (If ad-hoc UI edits must persist, set allowUiUpdates: true — but then the file and DB can drift.)
Prevention Best Practices
- Pick one source of truth per dashboard: either file provisioning (edit JSON in Git) or the UI — not both.
- For provisioned dashboards, set
allowUiUpdatesdeliberately and document it; a lock icon in the UI signals provisioned dashboards. - In automation, always GET the current
versionright before POSTing, or setoverwrite: trueintentionally. - Avoid editing the same dashboard in multiple tabs; use folders/permissions to reduce simultaneous human edits.
- Add a save
messagefrom CI so version history clearly attributes each change. - See more Grafana guides and the sibling provisioned-dashboard delete guide.
Quick Command Reference
# Current version + provisioned flag
curl -s -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/dashboards/uid/<uid> \
| jq '{version:.dashboard.version, provisioned:.meta.provisioned, updatedBy:.meta.updatedBy}'
# Who saved what (version history)
curl -s -H "Authorization: Bearer $TOKEN" \
"http://localhost:3000/api/dashboards/uid/<uid>/versions?limit=5" \
| jq '.[]|{version,createdBy,message}'
# Provisioning config
grep -R "allowUiUpdates\|updateIntervalSeconds\|path:" /etc/grafana/provisioning/dashboards/
# Force-save via API (overwrite)
curl -s -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-X POST http://localhost:3000/api/dashboards/db \
-d '{"dashboard": <json>, "overwrite": true, "message":"sync"}'
Conclusion
“Someone else has updated this dashboard” is optimistic-concurrency doing its job: the stored version moved past the one your browser holds, so Grafana refuses to overwrite blindly. Typical root causes:
- Concurrent human edits (or the same dashboard open in two tabs).
- Provisioning re-applying the dashboard from disk and bumping the version.
- Terraform/CI automation racing a live UI edit.
- An API client posting a stale cached
version.
Read the version history first — createdBy: provisioning between two human saves means your real fix is choosing a single source of truth, not clicking “Save anyway”.
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.