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

  1. 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>).
  2. Regenerate the plugin's schemas by rebuilding it (its build.rs autogenerates schema files) or delete and rebuild the plugin's `permissions/schema.json`.
  3. If it's your own plugin, fix the invalid schema in its global scope permission (usually malformed schemars output or manual edits).
  4. 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

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.

Related errors


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)