zed-industries/zed · error · anyhow::Error
failed to compile {} parser with clang: {}
Error message
failed to compile {} parser with clang: {} What it means
The tree-sitter grammar compilation step failed: the builder invokes the wasi-sdk clang to compile the grammar's parser.c (plus scanner.c/.cc if present) to a wasm module exporting tree_sitter_{grammar_name}, and a non-zero clang exit status bails with clang's stderr. {grammar_name} identifies which grammar in the extension.toml [grammars] table failed.
Source
Thrown at crates/extension/src/extension_builder.rs:351
"skipping compilation of {grammar_name} parser because the existing compiled grammar is up to date"
);
} else {
log::info!("compiling {grammar_name} parser");
let clang_output = util::command::new_command(&clang_path)
.args(["-fPIC", "-shared", "-Os"])
.arg(format!("-Wl,--export=tree_sitter_{grammar_name}"))
.arg("-o")
.arg(&grammar_wasm_path)
.arg("-I")
.arg(&src_path)
.arg(&parser_path)
.args(scanner_path.exists().then_some(scanner_path))
.output()
.await
.context("failed to run clang")?;
if !clang_output.status.success() {
bail!(
"failed to compile {} parser with clang: {}",
grammar_name,
String::from_utf8_lossy(&clang_output.stderr),
);
}
}
Ok(())
}
async fn checkout_repo(&self, directory: &Path, url: &str, rev: &str) -> Result<()> {
let git_dir = directory.join(".git");
if directory.exists() {
let remotes_output = util::command::new_command("git")
.arg("--git-dir")
.arg(&git_dir)
.args(["remote", "get-url", "origin"])View on GitHub (pinned to f4178619ac)
Solutions
- Read clang's stderr in the message - it names the file and line that failed
- Verify the pinned rev actually contains src/parser.c: clone the grammar repo, 'git checkout <rev>' and inspect src/
- If parser.c is missing, generate it with 'tree-sitter generate' upstream and pin to a rev that has it, or pick another rev
- Test-compile locally with the cached wasi-sdk clang using the same flags (-I src parser.c scanner.c -Wl,--export=tree_sitter_<name>) to iterate fast
- If clang itself failed (not the sources), clear the cached wasi-sdk dir under the extension builder cache to force a clean re-download
Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the pinned rev has generated parser sources before building
let has_parser = std::path::Path::new(&format!("{cache}/{grammar}/src/parser.c")).exists();
anyhow::ensure!(has_parser, "grammar {grammar} has no src/parser.c at rev {rev}"); Try / catch
if let Err(err) = build_result {
if err.to_string().contains("parser with clang") {
// err contains clang stderr: file/line of the failing C source
return Err(err.context("grammar C sources failed to compile - see clang diagnostics above"));
}
return Err(err);
} Prevention
- Pin grammar revs that contain generated src/parser.c; verify before releasing
- Compile new grammar versions locally with tree-sitter first to catch scanner/parser breakage
- Keep the wasi-sdk cache clean so clang failures are source failures, not toolchain failures
When it happens
Trigger: Running an extension build that includes grammars where clang rejects the C sources: missing generated parser.c at the pinned rev, scanner.c/scanner.cc errors, incompatible tree-sitter ABI (LANGUAGE_VERSION mismatch headers), clang running out of memory, or a broken/partial wasi-sdk in the cache.
Common situations: Grammar repo whose src/parser.c was never generated or was removed at the pinned commit; grammar written against a newer tree-sitter CLI than the vendored parser runtime; scanner using C++ features while being compiled as C; corrupted wasi-sdk download in the extension cache dir.
Related errors
- grammar name '{grammar_name}' must be written in snake_case:
- grammar directory '{}' already exists, but is not a git clon
- failed to run `git init` in directory '{}'
- extension dir {} is not an absolute path
- capability for process:exec {desired_command} {desired_args:
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/450e07abd286fbe5.
Report an issue: GitHub.