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

extension dir {} is not an absolute path

Error message

extension dir {} is not an absolute path

What it means

ExtensionBuilder::compile_extension() requires the extension_dir argument to be an absolute path and bails with this message after populate_defaults when extension_dir.is_relative(). The builder later does extension_dir.join(...) for cargo target dirs, manifest paths and wasm output, and sets it as cargo's current_dir, so relative paths would resolve against an unpredictable working directory.

Source

Thrown at crates/extension/src/extension_builder.rs:104

        Self {
            cache_dir,
            http: http_client,
        }
    }

    pub async fn compile_extension(
        &self,
        extension_dir: &Path,
        extension_manifest: &mut ExtensionManifest,
        options: CompileExtensionOptions,
        fs: Arc<dyn Fs>,
    ) -> Result<()> {
        let start = std::time::Instant::now();

        populate_defaults(extension_manifest, extension_dir, fs.clone()).await?;

        if extension_dir.is_relative() {
            bail!(
                "extension dir {} is not an absolute path",
                extension_dir.display()
            );
        }

        fs.create_dir(&self.cache_dir)
            .await
            .context("failed to create cache dir")?;

        let (tx, mut rx) = oneshot::channel();

        let clang_path = extension_manifest.grammars.is_empty().not().then(|| {
            std::iter::repeat_n(
                async {
                    self.install_wasi_sdk_if_needed()
                        .await
                        .log_err()
                        .map(Arc::new)

View on GitHub (pinned to f4178619ac)

Solutions

  1. Canonicalize before calling: let dir = std::fs::canonicalize(input_path)?; and pass &dir
  2. Or build an absolute path from a known root: let dir = std::env::current_dir()?.join(input);
  3. In tests, use absolute fixture paths (e.g. via CARGO_MANIFEST_DIR) rather than relative ones

Example fix

// before
let extension_dir = Path::new("extensions/my-ext");
builder.compile_extension(extension_dir, &mut manifest, options, fs).await?;

// after
let extension_dir = std::fs::canonicalize("extensions/my-ext")?;
builder.compile_extension(&extension_dir, &mut manifest, options, fs).await?;
Defensive patterns

Strategy: validation

Validate before calling

let extension_dir = std::fs::canonicalize(input_path)
    .context("resolve extension dir to an absolute path")?;
anyhow::ensure!(
    extension_dir.is_absolute(),
    "extension dir must be absolute: {}",
    input_path.display()
);

Prevention

When it happens

Trigger: Calling compile_extension(extension_dir, ...) with a path like "my-extension", "./ext/foo", or "../foo" - anything Path::is_relative() returns true for. Typical for programmatic users of the crates/extension builder API rather than the zed CLI (the CLI resolves its paths first).

Common situations: Scripts or CI code that passes the CLI argument straight through without canonicalization; tests using fixture-relative paths; switching code that worked under an assumed cwd to another launcher with a different working directory.

Related errors


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