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, orsignature modified. /api/pluginsdoesn’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 yourroot_url. - Keep
allow_loading_unsigned_pluginsto 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.jsonsits atplugins/<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:
- A private/internal plugin with no signature (
unsigned). - Files modified after signing, invalidating the MANIFEST (
modified/invalid). - A privately signed plugin whose embedded
root_urldoesn’t match Grafana’s. - A wrong/nested plugin directory so
plugin.jsoncan’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.
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.