tauri-apps/tauri · error · anyhow::Error

Permission {} not found, expected one of {}

Error message

Permission {} not found, expected one of {}

What it means

During tauri-build, every permission identifier referenced by a capability file (src-tauri/capabilities/*.json) is validated against the ACL manifests gathered from the application and its plugins. An identifier is resolved as <prefix>:<base>; the app's own ACL is the empty prefix. If the prefix is unknown or the base name is not a permission/permission-set in that manifest (with 'default' always accepted), the build fails and enumerates every permission that IS available.

Source

Thrown at crates/tauri-build/src/acl.rs:388

        let mut available_permissions = Vec::new();
        for (key, manifest) in acl_manifests {
          let prefix = if key == APP_ACL_KEY {
            "".to_string()
          } else {
            format!("{key}:")
          };
          if manifest.default_permission.is_some() {
            available_permissions.push(format!("{prefix}default"));
          }
          for p in manifest.permissions.keys() {
            available_permissions.push(format!("{prefix}{p}"));
          }
          for p in manifest.permission_sets.keys() {
            available_permissions.push(format!("{prefix}{p}"));
          }
        }

        anyhow::bail!(
          "Permission {} not found, expected one of {}",
          permission_id.get(),
          available_permissions.join(", ")
        );
      }
    }
  }

  Ok(())
}

pub fn build(out_dir: &Path, target: Target, attributes: &Attributes) -> super::Result<()> {
  let mut acl_manifests = read_plugins_manifests()?;

  let app_acl = app_manifest_permissions(
    out_dir,
    attributes.app_manifest,
    &attributes.inlined_plugins,

View on GitHub (pinned to 2f1cd75b0f)

Solutions

  1. Read the error output - it lists every available permission; correct the offending identifier in src-tauri/capabilities/*.json to one of them
  2. If the permission should exist, add or update the plugin crate in src-tauri/Cargo.toml (e.g. tauri-plugin-fs) so its ACL manifest is collected
  3. If the plugin was removed on purpose, delete its permission entries from the capability files
  4. Re-run tauri dev / tauri build after the fix to re-validate

Example fix

// before: src-tauri/capabilities/main.json
{ "permissions": ["fs:allow-readfile"] }

// after
{ "permissions": ["fs:allow-read-file"] }
Defensive patterns

Strategy: validation

Validate before calling

// prebuild check: dump every permission id used by capabilities
const { readdirSync, readFileSync } = require('fs')
for (const f of readdirSync('src-tauri/capabilities')) {
  const c = JSON.parse(readFileSync(`src-tauri/capabilities/${f}`, 'utf8'))
  for (const p of c.permissions) console.log(f, typeof p === 'string' ? p : p.identifier)
}
// cross-check each '<plugin>:<name>' against that plugin's permissions/ folder or docs before building

Prevention

When it happens

Trigger: Building or running a Tauri v2 app (cargo build / tauri dev) whose capabilities/*.json references an unknown permission: a typo (fs:allow-readf), a wrong prefix (shell-open instead of shell:allow-open), a permission from a plugin not present in Cargo.toml, or a permission renamed/removed in a plugin upgrade. Capabilities are only validated for the target being built, so platform-filtered files check on their target.

Common situations: Copy-pasting capability snippets from docs of a different plugin major version; removing a plugin dependency but leaving its capability entries behind; renaming permissions across plugin upgrades; hand-writing permissions instead of using tauri add.

Related errors


AI-assisted analysis of tauri-apps/tauri@2f1cd75b0f (2026-08-16). Data as JSON: /api/errors/a61bc07dda2b2ae9. Report an issue: GitHub.