zed-industries/zed · error
extension {} has invalid zed:api-version section: {:?}
Error message
extension {} has invalid zed:api-version section: {:?} What it means
parse_wasm_extension_version() scans a compiled extension's .wasm for the 'zed:api-version' custom section, which Zed's extension builder writes as exactly 6 raw bytes: three big-endian u16s (major, minor, patch). parse_wasm_extension_version_custom_section() returns None unless data.len() == 6, so any other payload - a string like "1.0.0", an empty section, truncated bytes - triggers this bail. The section is Zed's embedded record of which Extension API version the wasm was built against.
Source
Thrown at crates/extension/src/extension.rs:201
) -> Result<Option<DebugScenario>>;
async fn run_dap_locator(
&self,
locator_name: String,
config: SpawnInTerminal,
) -> Result<DebugRequest>;
}
pub fn parse_wasm_extension_version(extension_id: &str, wasm_bytes: &[u8]) -> Result<Version> {
let mut version = None;
for part in wasmparser::Parser::new(0).parse_all(wasm_bytes) {
if let wasmparser::Payload::CustomSection(s) =
part.context("error parsing wasm extension")?
&& s.name() == "zed:api-version"
{
version = parse_wasm_extension_version_custom_section(s.data());
if version.is_none() {
bail!(
"extension {} has invalid zed:api-version section: {:?}",
extension_id,
s.data()
);
}
}
}
// The reason we wait until we're done parsing all of the Wasm bytes to return the version
// is to work around a panic that can happen inside of Wasmtime when the bytes are invalid.
//
// By parsing the entirety of the Wasm bytes before we return, we're able to detect this problem
// earlier as an `Err` rather than as a panic.
version.with_context(|| format!("extension {extension_id} has no zed:api-version section"))
}
fn parse_wasm_extension_version_custom_section(data: &[u8]) -> Option<Version> {
if data.len() == 6 {View on GitHub (pinned to 5a9b9558db)
Solutions
- Rebuild the extension with the current toolchain: 'zed extension build' (or crates/extension extension_builder), which writes the correct 6-byte section
- If you emit the section yourself, write exactly 6 bytes: major, minor, patch as big-endian u16 each (e.g. version 0.6.0 -> [0x00,0x00, 0x00,0x06, 0x00,0x00])
- Avoid wasm post-processing steps that drop custom sections (check wasm-opt/wasm-strip flags), or re-add the section afterwards
- If the file was hand-modified or downloaded, recompile from source to eliminate corruption
Example fix
// before: writing the version as a string
section.data = b"0.6.0"; // len 5 -> 'invalid zed:api-version section'
// after: exactly 6 bytes, three big-endian u16s
let (major, minor, patch) = (0u16, 6u16, 0u16);
let mut data = Vec::new();
for part in [major, minor, patch] {
data.extend_from_slice(&part.to_be_bytes());
}
section.data = &data; // len 6 -> parses to Version::new(0, 6, 0) Defensive patterns
Strategy: validation
Validate before calling
// Verify the section length before handing the wasm to Zed
fn has_valid_api_version(wasm_bytes: &[u8]) -> bool {
for part in wasmparser::Parser::new(0).parse_all(wasm_bytes).flatten() {
if let wasmparser::Payload::CustomSection(s) = part
&& s.name() == "zed:api-version"
{
return s.data().len() == 6;
}
}
false
} Try / catch
match parse_wasm_extension_version(extension_id, &wasm_bytes) {
Ok(version) => Some(version),
Err(err) if err.to_string().contains("invalid zed:api-version") => {
log::warn!("skipping malformed extension {extension_id}: {err:#}");
None
}
Err(err) => return Err(err),
} Prevention
- Always build wasm through 'zed extension build' / extension_builder so the section format is correct
- Never write the version as a string - it is three big-endian u16s, exactly 6 bytes
- Skip wasm post-processors that strip custom sections, or re-emit the section afterwards
When it happens
Trigger: Loading or analyzing a Zed wasm extension whose zed:api-version custom section is not 6 bytes: wasm built by an outdated/foreign toolchain that wrote a different format (e.g. semver string or JSON), a hand-written build script that adds the custom section itself, or a corrupted/truncated .wasm file.
Common situations: Extension authors adding the section manually with a string version instead of binary u16 triples; wasm rebuilt or post-processed (wasm-opt/wasm-tools strip or rewrite custom sections); extensions compiled by mismatched Zed versions whose section format differed.
Related errors
- `run_slash_command` not available prior to v0.1.0
- `context_server_command` not available prior to v0.2.0
- `context_server_configuration` not available prior to v0.5.0
- `suggest_docs_packages` not available prior to v0.1.0
- `index_docs` not available prior to v0.1.0
AI-assisted analysis of zed-industries/zed@5a9b9558db (2026-08-20).
Data as JSON: /api/errors/6f5d97569a532d66.
Report an issue: GitHub.