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

Grafana Error Guide: 'plugin signature invalid' — Unsigned Plugins Not Loading

Fix 'plugin signature invalid' and unsigned plugin errors in Grafana — verify signatures, allow trusted unsigned plugins, fix modified files and wrong paths, and reload plugins safely.

  • #grafana
  • #troubleshooting
  • #errors
  • #plugins

Overview

Grafana verifies a cryptographic signature for every plugin at startup. Signed plugins from the catalog load normally; unsigned plugins (private/internal builds) and plugins whose files were modified after signing are refused by default and disabled. This is a security control — a tampered or unknown plugin won’t run unless you explicitly allow it.

The literal errors you will see:

logger=plugin.signature level=warn msg="Skipping loading plugin due to unsigned signature state" pluginID=my-custom-panel
logger=plugins level=error msg="Plugin signature invalid" pluginID=acme-datasource status=invalid
logger=plugin.signature msg="Plugin signature state modified" pluginID=acme-panel files="module.js"

It occurs at boot (and on plugin reload). The plugin never appears in the panel/data-source list, and the dashboards that depend on it show “panel plugin not found”.

Symptoms

  • A custom or third-party plugin is missing from the UI; dashboards show “Panel plugin not found”.
  • Startup log shows unsigned, signature invalid, or signature modified.
  • /api/plugins doesn’t list the plugin, or lists it as not enabled.
  • The plugin worked before an edit to its files (state becomes modified).
grep -iE "signature|unsigned" /var/log/grafana/grafana.log | tail
logger=plugin.signature msg="Skipping loading plugin due to unsigned signature state" pluginID=my-custom-panel

Common Root Causes

1. Private/internal plugin is unsigned

An in-house or forked plugin has no catalog signature. Grafana refuses it by default (signature=unsigned).

cat /var/lib/grafana/plugins/my-custom-panel/MANIFEST.txt 2>/dev/null || echo "no MANIFEST (unsigned)"

2. Files modified after signing → invalid signature

Editing any file in a signed plugin invalidates its MANIFEST hash; state becomes modified/invalid.

logger=plugin.signature msg="Plugin signature state modified" pluginID=acme-panel files="module.js"

3. Signature type mismatch (private signed for wrong root_url)

A privately signed plugin embeds the root_url(s) it was signed for. If Grafana’s URL doesn’t match, the signature is invalid.

4. Wrong plugin directory or nested path

The plugin was extracted one level too deep (e.g. plugins/my-panel/my-panel/plugin.json), so Grafana can’t find/verify it.

find /var/lib/grafana/plugins -name plugin.json

Diagnostic Workflow

Step 1: List plugins and signature state via API

curl -s -H "Authorization: Bearer $TOKEN" \
  http://localhost:3000/api/plugins?embedded=0 \
  | jq '.[] | {id, signature, signatureType, enabled}' | grep -A4 -i "<pluginID>"

Step 2: Read the signature log lines

journalctl -u grafana-server --no-pager | grep -iE "plugin.signature|signature invalid|unsigned" | tail -20

Distinguish unsigned (no signature) from invalid/modified (tampered/mismatched).

Step 3: Verify directory layout and MANIFEST

ls -la /var/lib/grafana/plugins/<pluginID>/
find /var/lib/grafana/plugins/<pluginID> -name plugin.json
test -f /var/lib/grafana/plugins/<pluginID>/MANIFEST.txt && echo "signed" || echo "unsigned"

Step 4: Allow trusted unsigned plugins (only if you trust them)

[plugins]
; comma-separated plugin IDs you explicitly trust
allow_loading_unsigned_plugins = my-custom-panel,acme-datasource

Restart Grafana and re-check the log:

systemctl restart grafana-server
journalctl -u grafana-server --no-pager | grep -i "<pluginID>" | tail

Step 5: For a modified signed plugin, reinstall cleanly

grafana-cli plugins uninstall <pluginID>
grafana-cli plugins install <pluginID>   # gets a pristine signed copy
systemctl restart grafana-server

Example Root Cause Analysis

After a Grafana upgrade, a team’s dashboards show “Panel plugin not found” for their internal acme-status-panel. The log:

logger=plugin.signature level=warn msg="Skipping loading plugin due to unsigned signature state" pluginID=acme-status-panel

The panel is an internal build with no catalog signature. It “worked before” only because the old deployment set allow_loading_unsigned_plugins, and that setting was dropped in the new config. /api/plugins confirms:

{"id":"acme-status-panel","signature":"unsigned","enabled":false}

Fix: re-add the explicit allowlist entry (the team owns and trusts this plugin):

[plugins]
allow_loading_unsigned_plugins = acme-status-panel

After systemctl restart grafana-server, the log shows the plugin loaded and the dashboards render. The longer-term fix is to privately sign the plugin (via grafana-toolkit/the signing service) for their root_url so it loads without the allowlist. Root cause: an unsigned internal plugin whose explicit trust setting was lost in a config change.

Prevention Best Practices

  • Prefer signed plugins: install from the catalog with grafana-cli plugins install, or privately sign internal plugins for your root_url.
  • Keep allow_loading_unsigned_plugins to a minimal, explicit list of plugins you own and trust — never blanket-allow.
  • Never edit files inside a signed plugin; fork and rebuild+resign instead (editing sets state to modified).
  • Watch plugin directory layout so plugin.json sits at plugins/<id>/plugin.json, not nested a level deeper.
  • Re-verify plugins after every Grafana upgrade and after config changes to [plugins].
  • See more Grafana guides.

Quick Command Reference

# Signature state per plugin
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:3000/api/plugins \
  | jq '.[]|{id,signature,signatureType,enabled}'

# Signature log lines
journalctl -u grafana-server | grep -iE "plugin.signature|unsigned|signature invalid" | tail

# Layout + MANIFEST
find /var/lib/grafana/plugins/<pluginID> -name plugin.json
test -f /var/lib/grafana/plugins/<pluginID>/MANIFEST.txt && echo signed || echo unsigned

# Allow a trusted unsigned plugin (grafana.ini)
#   [plugins]
#   allow_loading_unsigned_plugins = <pluginID>
systemctl restart grafana-server

# Reinstall a modified signed plugin cleanly
grafana-cli plugins uninstall <pluginID>
grafana-cli plugins install <pluginID>

Conclusion

“plugin signature invalid” / unsigned skips are Grafana’s supply-chain guard refusing to run a plugin it can’t verify. Typical root causes:

  1. A private/internal plugin with no signature (unsigned).
  2. Files modified after signing, invalidating the MANIFEST (modified/invalid).
  3. A privately signed plugin whose embedded root_url doesn’t match Grafana’s.
  4. A wrong/nested plugin directory so plugin.json can’t be found and verified.

Read the log to tell unsigned from invalid. For plugins you own, either add them to allow_loading_unsigned_plugins or, better, privately sign them; for tampered signed plugins, reinstall a pristine copy.

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.