Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Grafana By James Joyner IV · · 9 min read

Grafana Error Guide: 'Dashboard import failed / invalid JSON model' — Fix a Bad Dashboard Model

Fix Grafana 'failed to load dashboard' and invalid JSON model errors: diagnose malformed JSON, schema version mismatch, unmapped inputs, and provisioning load failures.

  • #grafana
  • #troubleshooting
  • #errors
  • #provisioning

Overview

Grafana stores every dashboard as a JSON model. When you import that model — through the UI, the HTTP API, or file provisioning — Grafana parses and validates it before saving. A malformed model, an unmapped input, or a newer schema than the running Grafana understands makes the import fail outright.

The literal errors you will see:

Dashboard import failed: invalid character '}' looking for beginning of object key string
The dashboard has been changed by someone else / invalid dashboard model
level=error logger=provisioning.dashboard msg="failed to load dashboard from" file=/var/lib/grafana/dashboards/app.json error="invalid character 'x' after top-level value"

Unlike a “Data source not found” (which loads but has no data), a JSON model failure means the dashboard never loads at all — the file is rejected during parsing.

Symptoms

  • UI import shows “Dashboard import failed” with a JSON parse position.
  • Provisioned dashboards never appear and the log shows failed to load dashboard from.
  • The API returns HTTP 400 with invalid character or unexpected end of JSON input.
  • After editing a dashboard file by hand, Grafana ignores it.

Common Root Causes

1. Malformed JSON

A trailing comma, unbalanced brace, or a template that left ${VAR} where JSON expected a value makes the parser fail immediately.

2. Wrong provisioning file wrapper

Provisioning expects the raw dashboard JSON, but the file contains an API-style {"dashboard": {...}, "overwrite": true} wrapper (or vice versa for the API).

3. Unresolved __inputs placeholders

A “share externally” export leaves ${DS_PROMETHEUS} inputs that are valid JSON strings but invalid as a runnable model on import.

4. Schema version too new

A dashboard exported from a newer Grafana carries a schemaVersion the older running instance cannot migrate.

5. Encoding / BOM issues

A UTF-8 BOM or CRLF artifacts prepended to the file break the JSON parser on the first byte.

Diagnostic Workflow

Step 1: Validate the JSON is well-formed

jq empty /var/lib/grafana/dashboards/app.json && echo "valid JSON" || echo "INVALID JSON"
python3 -m json.tool /var/lib/grafana/dashboards/app.json > /dev/null

jq prints the exact line/column of the first syntax error.

Step 2: Read the provisioning log for the reason

sudo journalctl -u grafana-server --no-pager | grep -iE "provisioning.dashboard|failed to load dashboard" | tail -20
kubectl logs deploy/grafana -n monitoring | grep -i "failed to load dashboard" | tail -20
grep -i "failed to load dashboard" /var/log/grafana/grafana.log | tail -20

Step 3: Confirm the correct file shape

For file provisioning the file must be the bare dashboard object. For the API it must be wrapped:

# API import expects a wrapper
curl -s -X POST -H "Authorization: Bearer $GRAFANA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dashboard": '"$(cat app.json)"', "overwrite": true}' \
  http://localhost:3000/api/dashboards/db | jq

A 400 with invalid character here points back at the JSON itself.

Step 4: Check for BOM/CRLF and schema version

head -c 3 app.json | xxd            # ef bb bf == UTF-8 BOM to strip
grep -o '"schemaVersion": *[0-9]*' app.json

If schemaVersion exceeds what your Grafana version supports, re-export from a matching version or import through the UI, which migrates older models forward.

Step 5: Point provisioning at the right folder

# /etc/grafana/provisioning/dashboards/default.yaml
apiVersion: 1
providers:
  - name: 'default'
    orgId: 1
    folder: 'Services'
    type: file
    disableDeletion: false
    options:
      path: /var/lib/grafana/dashboards

Example Root Cause Analysis

A CI job writes dashboards into /var/lib/grafana/dashboards, but one never shows up. The log:

logger=provisioning.dashboard msg="failed to load dashboard from" file=/var/lib/grafana/dashboards/app.json error="invalid character ',' looking for beginning of object key string"

Running jq empty app.json points at a trailing comma after the last panel object — valid to a templating tool, invalid JSON. The dashboard was rendered from a Jinja template that left a comma before the closing ].

Fix: remove the trailing comma (or pipe the template output through jq . in CI to normalize it before writing). Grafana’s provisioner rescans on its interval and the dashboard appears. The root cause was a template producing technically-invalid JSON, caught immediately by jq.

Prevention Best Practices

  • Run jq empty (or python3 -m json.tool) on every dashboard file in CI before it ships; see more Grafana guides.
  • Keep provisioning files as bare dashboard objects and API payloads wrapped — never mix the two shapes.
  • Strip UTF-8 BOMs and normalize line endings when generating JSON from templates.
  • Export dashboards from a Grafana version that matches production so schemaVersion migrates cleanly.
  • Resolve ${DS_*} inputs to real UIDs before provisioning instead of shipping raw share-externally exports.
  • Version dashboards in git and review diffs so a stray edit cannot silently break the model.

Quick Command Reference

# Validate JSON and pinpoint the syntax error
jq empty /var/lib/grafana/dashboards/app.json
python3 -m json.tool /var/lib/grafana/dashboards/app.json > /dev/null

# Why did provisioning reject it?
sudo journalctl -u grafana-server | grep -i "failed to load dashboard" | tail -20
kubectl logs deploy/grafana -n monitoring | grep -i "failed to load dashboard" | tail -20

# BOM / schema checks
head -c 3 app.json | xxd
grep -o '"schemaVersion": *[0-9]*' app.json

# API import (expects wrapper)
curl -s -X POST -H "Authorization: Bearer $GRAFANA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dashboard": '"$(cat app.json)"', "overwrite": true}' \
  http://localhost:3000/api/dashboards/db | jq

Conclusion

A “failed to load dashboard” / invalid JSON model error is a parse-time rejection — Grafana never gets far enough to render anything. Diagnose in order:

  1. Prove the file is valid JSON with jq empty; it names the exact bad character.
  2. Read the provisioning log for the precise reason (syntax vs. wrapper vs. schema).
  3. Match the file shape to the load path — bare object for provisioning, wrapped for the API.
  4. Strip BOM/CRLF and reconcile schemaVersion with your Grafana version.

Validate JSON in CI once and malformed models stop reaching Grafana at all.

Free download · 368-page PDF

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.