zed-industries/zed · error

invalid cat-file header: {header_line}

Error message

invalid cat-file header: {header_line}

What it means

load_revisions() parses the stdout of `git cat-file --batch`, where every response starts with a header line of the form `<oid> <type> <size>`. When a header line does not match any expected shape, this error is raised with the raw line included, and the whole batch fails.

Source

Thrown at crates/git/src/repository.rs:1813

                let output = std::str::from_utf8(&output.stdout)?;
                let shas = output
                    .lines()
                    .map(|line| {
                        if line.ends_with("missing") {
                            None
                        } else {
                            Some(line.to_string())
                        }
                    })
                    .collect::<Vec<_>>();

                if shas.len() != revs.len() {
                    // In an octopus merge, git cat-file still only outputs the first sha from MERGE_HEAD.
                    bail!("unexpected number of shas")
                }

                Ok(shas)
            })
            .boxed()
    }

    fn load_revisions(
        &self,
        revisions: Vec<String>,
    ) -> BoxFuture<'_, Result<Vec<Option<Vec<u8>>>>> {
        let git = self.git_binary();
        self.executor
            .spawn(async move {
                if revisions.is_empty() {
                    return Ok(Vec::new());
                }
                if let Some(revision) = revisions.iter().find(|revision| revision.contains('\n')) {
                    anyhow::bail!(
                        "revision spec {revision:?} contains a newline and cannot be passed to git cat-file --batch"
                    );
                }

View on GitHub (pinned to 5a9b9558db)

Solutions

  1. Check the header line printed in the message: if it ends with `missing`, the revision does not exist locally — fetch or drop it before batching.
  2. Resolve/verify every revision with `git rev-parse --verify` (and treat missing ones as `None`) before the batch call.
  3. If the line looks like garbage rather than a real git answer, suspect stream desync: ensure no other consumer reads from the cat-file process stdout.
  4. Upgrade the git binary if its batch output is nonstandard.
Defensive patterns

Strategy: try-catch

Validate before calling

for spec in &revisions {
    git.run(&["rev-parse", "--verify", &format!("{spec}^{{object}}"))]).await?;
}

Try / catch

match repo.load_revisions(revisions).await {
    Err(e) if e.to_string().contains("invalid cat-file header") => {
        // one revision likely does not resolve: re-check each with rev-parse and retry without it
    }
    other => other?,
}

Prevention

When it happens

Trigger: A revision in the batch does not resolve, so git answers a short line (e.g. `<spec> missing`) instead of a header; or the batch stream is desynchronized because a previous response body was not fully consumed (wrong size read); or an unexpected git version emits nonstandard batch output.

Common situations: Passing short SHAs, tags, or expressions that do not exist in the local object store; shallow or partial clones missing objects; a concurrent `git gc` pruning objects between listing and loading; earlier parsing bugs that left the stdout stream offset.

Related errors


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