tauri-apps/tauri · error

failed to resolve ACL

Error message

failed to resolve ACL

What it means

Thrown at build time when `Resolved::resolve` fails to combine the plugin ACL manifests and parsed capabilities into a resolved ACL for the build target. The `.expect` fires when capabilities reference unknown plugins/permissions, or the manifests and capabilities are mutually inconsistent (e.g. a permission listed in a capability does not exist in any manifest).

Solutions

  1. Check the compiler output above the panic for the specific unresolved permission/identifier and fix the capabilities/*.toml|json entry.
  2. Remove or update capabilities referencing plugins you no longer include.
  3. Update permission names to match the installed plugin versions (see plugin docs for renames).
  4. Clean the build dir (`cargo clean`) so stale manifests from removed plugins are regenerated.
  5. Verify custom permissions/permissions files are properly registered in build.rs / tauri.conf.json.

Example fix

// capabilities/default.json before
{"permissions": ["fs:allow-read-file", "old-plugin:do-thing"]}
// after (plugin removed)
{"permissions": ["fs:allow-read-file"]}
Defensive patterns

Strategy: validation

Validate before calling

// before building, verify every permission in capabilities exists in installed plugin manifests
const caps = JSON.parse(require('fs').readFileSync('src-tauri/capabilities/default.json', 'utf8'));
const pkg = JSON.parse(require('fs').readFileSync('src-tauri/Cargo.toml', 'utf8')); // or parse properly
for (const perm of caps.permissions) {
  const plugin = perm.split(':')[0];
  if (plugin !== 'core' && !permImplementedByInstalledPlugin(plugin, perm)) {
    console.error(`capability references unknown permission: ${perm}`);
  }
}

Prevention

When it happens

Trigger: `tauri build`/`tauri dev` where a capability references a plugin permission that is not present in the resolved manifest map, plugins were removed/renamed but capabilities still reference them, or the additional capabilities files are invalid for the target.

Common situations: Upgrading Tauri or removing a plugin without updating capabilities files; typos in permission names; plugin renamed permissions between versions; referencing app-defined permissions not yet registered.

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


AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18). Data as JSON: /api/errors/26591bb17a5ce447. Report an issue: GitHub.

Appendix: source

Thrown at crates/tauri-codegen/src/context.rs:419

    Default::default()
  };

  let capabilities_file_path = out_dir.join(CAPABILITIES_FILE_NAME);
  let capabilities_from_files = if capabilities_file_path.exists() {
    let capabilities_json =
      std::fs::read_to_string(&capabilities_file_path).expect("failed to read capabilities");
    serde_json::from_str(&capabilities_json).expect("failed to parse capabilities")
  } else {
    Default::default()
  };
  let capabilities = get_capabilities(
    &config,
    capabilities_from_files,
    additional_capabilities.as_deref(),
  )
  .unwrap();

  let resolved = Resolved::resolve(&acl, capabilities, target).expect("failed to resolve ACL");

  let acl_tokens = map_lit(
    quote! { ::std::collections::BTreeMap },
    &acl,
    str_lit,
    identity,
  );

  let runtime_authority = quote!(#root::runtime_authority!(#acl_tokens, #resolved));

  let plugin_global_api_scripts = if config.app.with_global_tauri {
    if let Some(scripts) = tauri_utils::plugin::read_global_api_scripts(&out_dir) {
      let scripts = scripts.into_iter().map(|s| quote!(#s));
      quote!(::std::option::Option::Some(&[#(#scripts),*]))
    } else {
      quote!(::std::option::Option::None)
    }
  } else {

View on GitHub (pinned to 460ec35447)