Grafana dashboard panel shows 'Datasource with UID ... not found' after migration
Dashboard panels display 'Datasource with UID <uid> not found'
Focused incident mode — strips away everything but this runbook.
Symptoms
- Dashboard panels display 'Datasource with UID <uid> not found'
- Panels go blank or show an error banner after a Grafana upgrade
- Datasource list in Grafana settings shows a different UID than the dashboard expects
- Importing a dashboard from another Grafana instance breaks all panels
UIDs are stable identifiers that survive Grafana upgrades but not delete-and-recreate. When migrating dashboards between instances, always re-import with datasource variable references instead of hardcoded UIDs.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Datasource UID in the dashboard JSON
curl -s -H 'Authorization: Bearer <TOKEN>' http://<GRAFANA>/api/dashboards/uid/<DASH-UID> | jq '.dashboard.panels[].datasource.uid'Available datasources
curl -s -H 'Authorization: Bearer <TOKEN>' http://<GRAFANA>/api/datasources | jq '.[] | {id, uid, name, type}'
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- The dashboard references a UID that does not exist in /api/datasources
- Datasource was recently deleted and recreated, or imported from another instance
- The old UID appears in the dashboard JSON but not in the live datasource list
Confirm before fixing
curl -s -H 'Authorization: Bearer <TOKEN>' http://<GRAFANA>/api/datasources | jq '.[].uid'List all live datasource UIDs
Fix
curl -s -X PUT -H 'Authorization: Bearer <TOKEN>' -H 'Content-Type: application/json' http://<GRAFANA>/api/datasources/<DS-ID> -d '{"uid":"<OLD-UID>"}'Update the datasource UID to match what the dashboard expects
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
curl -s -H 'Authorization: Bearer <TOKEN>' http://<GRAFANA>/api/datasources | jq '.[] | {uid, name, type}'List all datasource UIDs
curl -s -H 'Authorization: Bearer <TOKEN>' http://<GRAFANA>/api/dashboards/uid/<DASH-UID> | jq '[.dashboard.panels[].datasource.uid] | unique'Find which UIDs the dashboard references
curl -s -X PUT -H 'Authorization: Bearer <TOKEN>' -H 'Content-Type: application/json' http://<GRAFANA>/api/datasources/<DS-ID> -d '{"uid":"<CORRECT-UID>"}'Update the datasource UID to match the dashboard
Prevention
- Export dashboards with 'Export for sharing externally' to use template variables instead of UIDs.
- Use Grafana provisioning (YAML files) for datasources so UIDs are deterministic and version-controlled.
- Add a datasource UID consistency check to the Grafana upgrade runbook.
- Avoid manually editing datasource UIDs in the database — use the API.
Related runbooks
Same stack, same failure family — worth a skim.
up == 0 for one or more targets on the /targets page
Dashboard panels display 'No data' or an empty chart
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.