tauri-apps/tauri · error

invalid capability

Error message

invalid capability

What it means

RuntimeCapability is implemented for any &str/String: build() parses the string into a CapabilityFile, trying JSON first, then TOML. The expect panics when the string is neither valid JSON nor valid TOML, or does not match the capability schema (missing identifier, malformed permissions/webviews/remote fields). It backs Manager::add_capability, so app.add_capability("...") with a bad string panics.

Source

Thrown at crates/tauri/src/ipc/capability_builder.rs:22

use serde::Serialize;
use tauri_utils::{
  acl::{
    capability::{Capability, CapabilityFile, PermissionEntry},
    Scopes,
  },
  platform::Target,
};

/// A capability that can be added at runtime.
pub trait RuntimeCapability {
  /// Creates the capability file.
  fn build(self) -> CapabilityFile;
}

impl<T: AsRef<str>> RuntimeCapability for T {
  fn build(self) -> CapabilityFile {
    self.as_ref().parse().expect("invalid capability")
  }
}

/// A builder for a [`Capability`].
pub struct CapabilityBuilder(Capability);

impl CapabilityBuilder {
  /// Creates a new capability builder with a unique identifier.
  pub fn new(identifier: impl Into<String>) -> Self {
    Self(Capability {
      identifier: identifier.into(),
      description: "".into(),
      remote: None,
      local: true,
      windows: Vec::new(),
      webviews: Vec::new(),
      permissions: Vec::new(),
      platforms: None,

View on GitHub (pinned to 52e4b6e71d)

Solutions

  1. Pre-parse to see the real error: let r: Result<CapabilityFile, _> = s.parse(); inspect the Err before calling add_capability.
  2. Use JSON or TOML only, with required fields (identifier, permissions) present.
  3. If sourcing from a file, read it to a string first (include_str!) and validate contents, not the path.

Example fix

// before
app.add_capability("capabilities/beta/cap.json"); // path, not contents

// after
let raw = include_str!("../capabilities/beta/cap.json");
let parsed: tauri_utils::acl::capability::CapabilityFile = raw.parse().expect("capability file must be valid JSON/TOML");
app.add_capability(raw);
Defensive patterns

Strategy: validation

Validate before calling

// validate before handing the string to add_capability
let cap: Result<tauri_utils::acl::capability::CapabilityFile, _> = raw.parse();
assert!(cap.is_ok(), "capability string is not valid JSON/TOML: {:?}", cap.err());
app.add_capability(raw);

Type guard

fn is_valid_capability_str(s: &str) -> bool {
    s.parse::<tauri_utils::acl::capability::CapabilityFile>().is_ok()
}

Prevention

When it happens

Trigger: Passing a malformed or wrong-format capability string to app.add_capability: YAML capability content (only JSON/TOML are parsed), JSON missing required fields such as identifier, or a file path instead of the file contents.

Common situations: Copying a capabilities/*.yaml file's content into runtime code; hand-written JSON typos; passing a path where contents were expected.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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