zed-industries/zed · error · anyhow::Error

capability for npm:install {package_name} is not granted by

Error message

capability for npm:install {package_name} is not granted by the extension host

What it means

The host gates npm package installation for WASM extensions through CapabilityGranter::grant_npm_install_package. An `npm:install` capability in the manifest must allow the exact package name (the pattern may only be the exact name or `*`). When the requested package is not granted, it bails naming the package.

Source

Thrown at crates/extension_host/src/capability_granter.rs:79

            );
        }

        Ok(())
    }

    pub fn grant_npm_install_package(&self, package_name: &str) -> Result<()> {
        let is_allowed = self
            .granted_capabilities
            .iter()
            .any(|capability| match capability {
                ExtensionCapability::NpmInstallPackage(capability) => {
                    capability.allows(package_name)
                }
                _ => false,
            });

        if !is_allowed {
            bail!("capability for npm:install {package_name} is not granted by the extension host",);
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;

    use extension::{ProcessExecCapability, SchemaVersion};

    use super::*;

    fn extension_manifest() -> ExtensionManifest {
        ExtensionManifest {
            id: "test".into(),
            name: "Test".to_string(),

View on GitHub (pinned to f4178619ac)

Solutions

  1. Add an [[capabilities]] kind = "npm:install" entry whose `package` exactly equals the name in the error message.
  2. If the extension legitimately installs a fixed, known set of packages, list each one; only use package = "*" when every install is user-driven and trusted.
  3. Rebuild and re-test the extension so the manifest is re-read.

Example fix

# before
[[capabilities]]
kind = "npm:install"
package = "tree-sitter-javascript"

# after: also grant the newly added package
[[capabilities]]
kind = "npm:install"
package = "tree-sitter-javascript"

[[capabilities]]
kind = "npm:install"
package = "tree-sitter-typescript"
Defensive patterns

Strategy: validation

Validate before calling

fn npm_install_allowed(manifest: &ExtensionManifest, package_name: &str) -> bool {
    manifest.capabilities.iter().any(|capability| match capability {
        ExtensionCapability::NpmInstallPackage(capability) => capability.allows(package_name),
        _ => false,
    })
}

// before installing from extension code
assert!(npm_install_allowed(&manifest, "tree-sitter-typescript"),
    "package lacks an npm:install capability");

Type guard

fn is_npm_install_capable(capability: &ExtensionCapability) -> bool {
    matches!(capability, ExtensionCapability::NpmInstallPackage(_))
}

Prevention

When it happens

Trigger: Extension code calls the npm install guest function for a package that has no matching [[capabilities]] kind = "npm:install" entry — e.g. version-suffixed names, scoped packages (@scope/name) added later, or dynamically chosen packages.

Common situations: Language extensions that lazily install grammars/tools per language and the manifest only allowlists some of them; typos or name drift between the code's package string and the manifest entry; new optional dependency added without a capability entry.

Related errors


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/1bbf033d814ba933. Report an issue: GitHub.