tauri-apps/tauri · error
invalid JSON schema for plugin
Error message
invalid JSON schema for plugin {name}: {e} What it means
While generating the JSON schema for capabilities/permissions (used by tooling and editor validation), Tauri collects each plugin's `global_scope_schema`. If a plugin's schema fails to deserialize as a valid JSON schema, generation panics. This indicates a broken or malformed schema inside a plugin manifest, not a problem in your app code.
Solutions
- Identify the offending plugin from the `{name}` in the message and update it to a version compatible with your Tauri version (cargo update -p <plugin>).
- Regenerate the plugin's schemas by rebuilding it (its build.rs autogenerates schema files) or delete and rebuild the plugin's `permissions/schema.json`.
- If it's your own plugin, fix the invalid schema in its global scope permission (usually malformed schemars output or manual edits).
- Clear stale build artifacts (cargo clean) so stale autogenerated schemas are regenerated.
Example fix
// before (plugin permissions/autogenerated/default.toml referencing a bad schema) # manually edited schema.json with unsupported "$recursiveRef" // after: regenerate $ cargo clean -p my-plugin && cargo build
Defensive patterns
Strategy: fallback
Validate before calling
// before building, sanity check plugin schema files for f in plugins/*/permissions/schema.json; do jq empty "$f" || echo "invalid JSON: $f"; done
Try / catch
// This panics in build scripts, so guard at dependency level: // pin plugin versions in Cargo.toml and verify the plugin builds standalone // cargo build -p tauri-plugin-foo
Prevention
- Keep tauri, tauri-utils, and all tauri-plugin-* crates on compatible versions
- Never hand-edit plugin-generated schema.json files
- Rebuild plugins (cargo clean) after upgrading Tauri major/minor versions
When it happens
Trigger: `generate_capability_schema` iterates the ACL and calls `global_scope_schema()` on each plugin manifest; a plugin ships a `global.json` (global scope schema) that fails schemars/serde validation, typically due to unsupported or malformed schema keywords.
Common situations: Using a third-party plugin built against an incompatible tauri/tauri-utils version; hand-editing a plugin's autogenerated schema files; a plugin release with a corrupted or outdated `permissions/` directory.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to define permissions for
- failed to define permissions for `core:default
- failed to read plugin global API script
- Permission not found, expected one of
- unable to autogenerate core:default set
AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18).
Data as JSON: /api/errors/51c20c4b99c7b45d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tauri-utils/src/acl/schema.rs:269
if let Some(Schema::Object(obj)) = root_schema.definitions.get_mut("PermissionEntry") {
let any_of = obj.subschemas().any_of.as_mut().unwrap();
let Schema::Object(extend_permission_entry) = any_of.last_mut().unwrap() else {
unreachable!("PermissionsEntry should be an object not a boolean");
};
// remove default properties and save it to be added later as a fallback
let obj = extend_permission_entry.object.as_mut().unwrap();
let default_properties = std::mem::take(&mut obj.properties);
let default_identifier = default_properties.get(IDENTIFIER).cloned().unwrap();
let default_identifier = (IDENTIFIER.to_string(), default_identifier);
let mut all_of = vec![];
let schemas = acl.iter().filter_map(|(name, manifest)| {
manifest
.global_scope_schema()
.unwrap_or_else(|e| panic!("invalid JSON schema for plugin {name}: {e}"))
.map(|s| (s, manifest.gen_possible_permission_schemas(Some(name))))
});
for ((scope_schema, defs), acl_perm_schema) in schemas {
let mut perm_schema = SchemaObject::default();
perm_schema.subschemas().any_of = Some(acl_perm_schema);
let mut if_schema = SchemaObject::default();
if_schema.object().properties = [(IDENTIFIER.to_string(), perm_schema.into())].into();
let mut then_schema = SchemaObject::default();
then_schema.object().properties = [
(ALLOW.to_string(), scope_schema.clone()),
(DENY.to_string(), scope_schema.clone()),
]
.into();
let mut obj = SchemaObject::default();View on GitHub (pinned to 460ec35447)