zed-industries/zed · error

unsupported raw diff status {status}

Error message

unsupported raw diff status {status}

What it means

parse_git_diff_raw_entry parses `git diff --raw -z --no-renames` metadata (:old_mode new_mode old_oid new_oid STATUS) and only maps the status letters M, T, A, D onto StatusCode. Any other status token bails with the token included. The invoking commands pass --no-renames, so C/R normally never appear; the realistic triggers are unmerged (U*/AA/DD...) entries from diffing against a conflicted worktree and exotic statuses (X, B).

Source

Thrown at crates/git/src/commit.rs:216

fn parse_git_diff_raw_entry<'a>(metadata: &'a str, path: &'a str) -> Result<CommitDiffEntry<'a>> {
    let mut fields = metadata
        .strip_prefix(':')
        .context("raw diff metadata is missing its ':' prefix")?
        .split_ascii_whitespace();
    let old_mode = fields.next().context("raw diff is missing the old mode")?;
    let new_mode = fields.next().context("raw diff is missing the new mode")?;
    let old_oid = fields
        .next()
        .context("raw diff is missing the old object ID")?;
    let new_oid = fields
        .next()
        .context("raw diff is missing the new object ID")?;
    let status = match fields.next() {
        Some("M") => StatusCode::Modified,
        Some("T") => StatusCode::TypeChanged,
        Some("A") => StatusCode::Added,
        Some("D") => StatusCode::Deleted,
        Some(status) => anyhow::bail!("unsupported raw diff status {status}"),
        None => anyhow::bail!("raw diff is missing the status"),
    };

    Ok(CommitDiffEntry {
        path,
        status,
        old_object: (!old_oid.bytes().all(|byte| byte == b'0')).then(|| CommitDiffObject {
            oid: old_oid,
            kind: if old_mode == GITLINK_MODE {
                CommitDiffObjectKind::Gitlink
            } else {
                CommitDiffObjectKind::Blob
            },
        }),
        new_object: (!new_oid.bytes().all(|byte| byte == b'0')).then(|| CommitDiffObject {
            oid: new_oid,
            kind: if new_mode == GITLINK_MODE {
                CommitDiffObjectKind::Gitlink

View on GitHub (pinned to f4178619ac)

Solutions

  1. Resolve or abort the in-progress merge/rebase/cherry-pick so the worktree has no unmerged index entries, then retry
  2. If you control the code, extend the match to map unmerged/copy/rename tokens (e.g. s.starts_with('U'), 'C*', 'R*') onto an existing StatusCode instead of bailing
  3. Verify with `git diff --raw -z --no-renames --merge-base <base>` in the repo to see the offending status letter

Example fix

// before
Some(status) => anyhow::bail!("unsupported raw diff status {status}"),

// after — collapse statuses the enum cannot distinguish
Some("U") | Some("X") | Some("B") => StatusCode::Modified,
Some(s) if s.starts_with('U') || s.starts_with('C') || s.starts_with('R') => StatusCode::Modified,
Defensive patterns

Strategy: type-guard

Validate before calling

// before consuming parse_git_diff_raw entries
for entry in parse_git_diff_raw(&stdout) {
    let entry = entry?; // guard: filter or map unsupported statuses before constructing CommitDiffEntry
}

Type guard

fn is_supported_raw_status(status: &str) -> bool {
    matches!(status, "M" | "T" | "A" | "D")
}

Try / catch

match entry {
    Ok(parsed) => { /* ... */ }
    Err(e) if e.to_string().contains("unsupported raw diff status") => { /* skip entry; likely unmerged index */ }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: DiffTreeType::MergeBaseWithWorktree runs `git diff --raw -z --merge-base <base>` against a worktree with unresolved merge conflicts, producing lines like ':000000 100644 ... AA' or ':100644 100644 ... UU'; the parser hits 'AA'/'UU' and bails.

Common situations: Opening the diff/commit view while a merge or rebase is mid-conflict; or a git config/tool emitting rename/copy statuses despite --no-renames.

Related errors


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