tauri-apps/tauri · error

invalid identifier in permission set?

Error message

invalid identifier in permission set?

What it means

Panic during ACL resolution while expanding a permission set: each entry is parsed with Identifier::try_from(perm.clone()).expect("invalid identifier in permission set?"). Identifiers must be non-empty lowercase ASCII with hyphens (not leading/trailing), at most one `:` separator, a non-empty base after the prefix, and must not start with `tauri-plugin`. Any entry violating these rules ("", "fs:", "a:b:c", "Camel", "-x") aborts the build.

Source

Thrown at crates/tauri-utils/src/acl/resolved.rs:434

// get the permissions from a permission set
fn get_permission_set_permissions<'a>(
  permission_id: &Identifier,
  acl: &'a BTreeMap<String, Manifest>,
  manifest: &'a Manifest,
  set: &'a PermissionSet,
) -> Result<Vec<TraversedPermission<'a>>, Error> {
  let key = permission_id.get_prefix().unwrap_or(APP_ACL_KEY);

  let mut permissions = Vec::new();

  for perm in &set.permissions {
    // a set could include permissions from other plugins
    // for example `dialog:default`, could include `fs:default`
    // in this case `perm = "fs:default"` which is not a permission
    // in the dialog manifest so we check if `perm` still have a prefix (i.e `fs:`)
    // and if so, we resolve this prefix from `acl` first before proceeding
    let id = Identifier::try_from(perm.clone()).expect("invalid identifier in permission set?");
    let (manifest, permission_id, key, permission_name) =
      if let Some((new_key, manifest)) = id.get_prefix().and_then(|k| acl.get(k).map(|m| (k, m))) {
        (manifest, &id, new_key, id.get_base())
      } else {
        (manifest, permission_id, key, perm.as_str())
      };

    if permission_name == "default" {
      permissions.extend(
        manifest
          .default_permission
          .as_ref()
          .map(|default| get_permission_set_permissions(permission_id, acl, manifest, default))
          .transpose()?
          .unwrap_or_default(),
      );
    } else if let Some(permission) = manifest.permissions.get(permission_name) {
      permissions.push(TraversedPermission {

View on GitHub (pinned to 52e4b6e71d)

Solutions

  1. Locate the failing set — the panic happens while resolving the set named just above in the build log; open that plugin's or app's permissions file
  2. Fix entries to `plugin-name:permission-name` or bare `permission-name`: lowercase, single optional colon, no leading/trailing hyphen, never starting with `tauri-plugin`
  3. Add a unit test that runs each set entry through tauri_utils::acl::Identifier::try_from to surface real parse errors
  4. cargo clean and rebuild after fixing the manifest

Example fix

# permissions/sets.toml — before
[[set]]
permissions = ["fs:", "Core:default"]

# after
[[set]]
permissions = ["fs:default", "core:default"]
Defensive patterns

Strategy: type-guard

Validate before calling

// run in CI over every permission-set entry read from permissions/*.toml
for perm in set_entries {
    assert!(is_valid_permission_id(&perm), "bad identifier: {perm}");
}

Type guard

pub fn is_valid_permission_id(s: &str) -> bool {
    tauri_utils::acl::Identifier::try_from(s.to_string()).is_ok()
}

Prevention

When it happens

Trigger: A permission set in a plugin manifest or app-level permissions file whose `permissions` array contains a malformed reference — empty string, prefix without base (`fs:`), double separator, uppercase/invalid characters, or a `tauri-plugin*` prefix.

Common situations: Hand-writing permissions/*.toml for a plugin; scripts that generate permission files and emit empty strings for missing commands; copy-paste typos like `core:window:default:` or `Shell:default`.

Related errors


AI-assisted analysis of tauri-apps/tauri@52e4b6e71d (2026-08-20). Data as JSON: /api/errors/999441399a901717. Report an issue: GitHub.