tauri-apps/tauri · error
Permission not found, expected one of
Error message
Permission {} not found, expected one of {} What it means
tauri-build's ACL validation (validate_capabilities) fails when a capability file references a permission_id that does not exist in any known plugin's or core's permission manifest. The error lists every available permission so the developer can correct the identifier. This is a build-time gate: bad ACL references would otherwise silently produce a mis-permissioned app.
Solutions
- Copy the exact identifier from the 'expected one of' list printed by the error into your capability file
- Add the plugin as a dependency in Cargo.toml/package.json so its permission manifest is registered
- Check for renames after upgrading a plugin — update capability files to the new permission names
- Fix the prefix format in the permission id (plugin-name:permission-name, core permissions use core: prefixes)
Example fix
// before (src-tauri/capabilities/default.json) "permissions": ["fs:readfile", "shell-open"] // after "permissions": ["fs:read-file", "shell:allow-open"]
Defensive patterns
Strategy: validation
Validate before calling
const KNOWN: &[&str] = &["core:default", "shell:allow-open", "fs:read-file", "opener:default"];
fn permissions_valid(perms: &[String]) -> bool {
perms.iter().all(|p| KNOWN.contains(&p.as_str()))
} Try / catch
// tauri_build::build() returns Result — fail the build script with context:
if let Err(e) = tauri_build::try_build(attrs) {
eprintln!("ACL validation failed: {e}");
std::process::exit(1);
} Prevention
- Copy permission identifiers from plugin docs / the error's 'expected one of' list, never hand-type them
- Add the corresponding plugin dependency before referencing its permissions
- After upgrading plugins, diff permission names in capability files
- Run `tauri build` (or `cargo build` in src-tauri) early to catch ACL typos
When it happens
Trigger: A `permissions` entry in src-tauri/capabilities/*.json names a permission (e.g. "fs:read-file" vs actual "fs:read-file" casing/path variants, or a plugin not installed) that no manifest declares; validate_capabilities runs during tauri build / build().
Common situations: Typo'd permission identifiers; referencing a plugin permission without adding the plugin as a dependency; permission renamed in a plugin upgrade; wrong `identifier` prefix (missing `plugin-name:` or extra prefix); hand-editing capability JSON.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- failed to resolve ACL
- unable to autogenerate
- unable to autogenerate default permissions
- Could not find a capability to update
- Couldn't find capabilities directory at
AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18).
Data as JSON: /api/errors/a61bc07dda2b2ae9.
Report an issue: GitHub.
Appendix: 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 460ec35447)