zed-industries/zed · error
unexpected number of shas
Error message
unexpected number of shas
What it means
While resolving MERGE_HEAD, the code feeds each rev to `git cat-file` and maps lines to Option<String> (None for "missing"), then requires shas.len() == revs.len(). In an octopus merge MERGE_HEAD lists multiple shas but the batched cat-file invocation only yields one, so the counts diverge and it bails — the inline comment documents this exact git behavior. It is a known upstream limitation, not a repository corruption signal.
Source
Thrown at crates/git/src/repository.rs:1746
.envs(env.iter())
.arg(path.as_unix_str())
.output()
.await?;
anyhow::ensure!(
output.status.success(),
"Failed to stage:\n{}",
String::from_utf8_lossy(&output.stderr)
);
} else {
log::debug!("removing path {path:?} from the index");
let output = git
.build_command(&["update-index", "--force-remove", "--"])
.envs(env.iter())
.arg(path.as_unix_str())
.output()
.await?;
anyhow::ensure!(
output.status.success(),
"Failed to unstage:\n{}",
String::from_utf8_lossy(&output.stderr)
);
}
Ok(())
})
.boxed()
}
fn remote_urls(&self) -> BoxFuture<'_, HashMap<String, String>> {
let git = self.git_binary();
self.executor
.spawn(async move {
if let Ok(stdout) = git.run(&["remote", "-v"]).await {
parse_remote_urls(&stdout)
} else {View on GitHub (pinned to 5a9b9558db)
Solutions
- Finish or abort the octopus merge (git merge --abort) and redo it as sequential pairwise merges, then retry
- Pass each rev as a separate cat-file argument (or loop) so every MERGE_HEAD line gets a sha, if you control the code
- Track/patch the upstream issue so MERGE_HEAD is parsed line-wise instead of via batched cat-file
Defensive patterns
Strategy: try-catch
Validate before calling
// before resolving merge-head shas: count MERGE_HEAD lines
let merge_head = smol::fs::read_to_string(".git/MERGE_HEAD").await?;
if merge_head.lines().count() > 1 {
// octopus merge: known cat-file limitation, handle before calling load_merge_head
} Try / catch
match load_merge_head().await {
Ok(shas) => Ok(shas),
Err(e) if e.to_string().contains("unexpected number of shas") => {
// octopus merge in progress: read .git/MERGE_HEAD line-wise as the source of truth
parse_merge_head_file().await
}
Err(e) => Err(e),
} Prevention
- Prefer sequential pairwise merges over `git merge a b c` octopus merges
- Parse MERGE_HEAD directly (one sha per line) when multi-parent merges must be supported
When it happens
Trigger: Loading merge-head shas while an octopus merge (merging 2+ branches at once, MERGE_HEAD with multiple lines) is in progress.
Common situations: Starting a commit-message flow during `git merge branch-a branch-b`, or scripts/extensions initiating multi-branch merges; anything that reads merge parents mid-octopus-merge hits it.
Related errors
- revision spec {revision:?} contains a newline and cannot be
- invalid cat-file header: {header_line}
- object not found: {}
- expected commit object, got {object_type}
- grammar directory '{}' already exists, but is not a git clon
AI-assisted analysis of zed-industries/zed@5a9b9558db (2026-08-20).
Data as JSON: /api/errors/1b84c758712d990a.
Report an issue: GitHub.