tauri-apps/tauri · error
invalid permission identifier
Error message
invalid permission identifier '{permission}' What it means
CapabilityBuilder::permission pushes a permission reference into a capability being built. The string is converted into a `PermissionEntry::PermissionRef` identifier via TryFrom; if the string is not a valid permission identifier, the builder panics rather than producing a capability with a malformed permission.
Solutions
- Use a valid permission identifier string (e.g. `"core:default"`, `"fs:allow-read"`) matching the `plugin-or-core:permission` grammar.
- Prefer the manifest-generated constants where available instead of hand-typed strings to avoid typos.
- Validate the identifier before building: attempt `permission.try_into()` (the same TryInto used internally) and handle the Err.
- For user-supplied permission lists, parse/validate all entries before constructing the CapabilityBuilder.
Example fix
// before
let perms = std::env::var("PERMS").unwrap_or_default();
let cap = CapabilityBuilder::new("main").permission(perms); // panics on empty string
// after
let perms = std::env::var("PERMS").unwrap_or_default();
let mut cap = CapabilityBuilder::new("main");
for p in perms.split(',') {
if let Ok(id) = p.trim().to_string().try_into() {
cap = cap.permission(id);
} else {
eprintln!("skipping invalid permission: {p}");
}
} Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_permission(s: &str) -> bool {
!s.is_empty()
&& s.parse::<tauri::ipc::CapabilityFilePermissionIdentifier>() .is_ok()
}
// or generically: let Ok(id) = permission.clone().try_into() else { return Err(...) }; Prevention
- Validate permission strings with TryInto before passing to the builder
- Use generated permission constants rather than raw strings
- Reject empty and un-prefixed entries from user/config input
- Check plugin docs for exact permission identifiers per version
When it happens
Trigger: Calling `.permission("...")` with a string that fails the identifier conversion — e.g. empty string, invalid characters, or a name not shaped like `plugin:permission-name` / valid set-name.
Common situations: Typo'd permission names in capability DSL code, concatenating identifiers dynamically and producing empty/invalid strings, using bare plugin names without the `plugin:` prefix when required by the identifier grammar.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18).
Data as JSON: /api/errors/03d550cd61c5dcbb.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tauri/src/ipc/capability_builder.rs:95
}
/// Link this capability to the a list of window labels.
pub fn webviews(mut self, webviews: impl IntoIterator<Item = impl Into<String>>) -> Self {
self
.0
.webviews
.extend(webviews.into_iter().map(|w| w.into()));
self
}
/// Add a new permission to this capability.
pub fn permission(mut self, permission: impl Into<String>) -> Self {
let permission = permission.into();
self.0.permissions.push(PermissionEntry::PermissionRef(
permission
.clone()
.try_into()
.unwrap_or_else(|_| panic!("invalid permission identifier '{permission}'")),
));
self
}
/// Add a new scoped permission to this capability.
pub fn permission_scoped<T: Serialize>(
mut self,
permission: impl Into<String>,
allowed: Vec<T>,
denied: Vec<T>,
) -> Self {
let permission = permission.into();
let identifier = permission
.clone()
.try_into()
.unwrap_or_else(|_| panic!("invalid permission identifier '{permission}'"));
let allowed_scope = allowedView on GitHub (pinned to 460ec35447)