tauri-apps/tauri · error
failed to resolve ACL
Error message
failed to resolve ACL
What it means
Build-time panic in tauri-codegen when merging the ACL: Resolved::resolve(&acl, capabilities, target).expect("failed to resolve ACL") fails when the app's capabilities cannot be resolved against the plugin manifests in acl-manifests.json — typically a permission that no manifest defines, an unknown permission-set entry, or permission scoping (platform/target/remote rules) that cannot be satisfied.
Source
Thrown at crates/tauri-codegen/src/context.rs:417
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 52e4b6e71d)
Solutions
- Read the full build log just above the panic — Tauri names the exact capability and permission that failed to resolve
- Check every permission listed in src-tauri/capabilities/*.json against the plugin's permissions/ folder (or its docs) and fix typos, renames, and removed permissions
- Confirm the plugin providing each permission is still a dependency: `cargo tree | grep <plugin>`
- cargo clean after adding/removing plugins so acl-manifests.json is regenerated
- Verify each capability's `platforms`/`windows` fields are consistent with the permissions used
Example fix
// src-tauri/capabilities/default.json — before "permissions": ["core:webview:defualt"] // after "permissions": ["core:webview:default"]
Defensive patterns
Strategy: validation
Validate before calling
// CI unit test: resolve the ACL with real error messages instead of a codegen panic
#[test]
fn acls_resolve() {
let acl = read_acl_manifests(); // parse OUT_DIR/acl-manifests.json
let caps = read_capabilities(); // parse OUT_DIR/capabilities.json
tauri_utils::acl::resolved::Resolved::resolve(&acl, caps, target)
.expect("ACL resolution must succeed — the panic in codegen hides this error");
} Prevention
- Treat permission identifiers like code: review every entry in capabilities/*.json against the plugin's permissions folder
- Clean the build after adding or removing plugins
- When upgrading plugins, check their changelogs for renamed or removed permissions
When it happens
Trigger: A capability file in src-tauri/capilities/*.json listing a permission identifier that does not exist (typo), a permission of a plugin removed from Cargo.toml, a permission with scope/remote-url constraints that conflict with the capability, or a stale acl-manifests.json after adding/removing plugins without a clean rebuild.
Common situations: Copying a capability file from another project whose plugin set differs; upgrading a plugin that renamed/removed a permission; typos like `core:webview:defualt`; adding a plugin but building against a cached manifest map.
Related errors
- failed to read capabilities
- failed to parse capabilities
- unable to create autogenerated commands dir
- unable to autogenerate {default_permission_path:?}
- invalid permission {p}
AI-assisted analysis of tauri-apps/tauri@52e4b6e71d (2026-08-20).
Data as JSON: /api/errors/26591bb17a5ce447.
Report an issue: GitHub.