zed-industries/zed · error

revision spec {revision:?} contains a newline and cannot be

Error message

revision spec {revision:?} contains a newline and cannot be passed to git cat-file --batch

What it means

load_revisions() batches revision lookups by writing every spec to the stdin of one `git cat-file --batch` process. The batch protocol delimits requests by newline, so a revision spec that itself contains a newline would be split into extra requests and desynchronize the responses. The library therefore rejects the whole batch before spawning git when any revision contains a newline.

Source

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

                        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 {
                    HashMap::default()
                }
            })
            .boxed()
    }

    fn revparse_batch(&self, revs: Vec<String>) -> BoxFuture<'_, Result<Vec<Option<String>>>> {
        let git = self.git_binary();
        self.executor
            .spawn(async move {
                let mut process = git
                    .build_command(&["cat-file", "--batch-check=%(objectname)"])
                    .stdin(Stdio::piped())
                    .stdout(Stdio::piped())
                    .stderr(Stdio::piped())
                    .spawn()?;

                let stdin = process
                    .stdin

View on GitHub (pinned to 5a9b9558db)

Solutions

  1. Trim and validate revision strings before passing them in: reject any spec containing a newline (and ideally enforce a strict revision charset such as A-Za-z0-9._/^~@:%-).
  2. Sanitize at the input boundary (trim user-pasted text) instead of at the git call site.
  3. Resolve each spec to a full SHA individually with `git rev-parse --verify <spec>` first, then batch the resolved SHAs, which are guaranteed newline-free.
  4. If the newline arrived via a ref you created, fix the script that created the malformed ref.

Example fix

// before
let contents = repo.load_revisions(vec![revision_from_user.clone()]).await?;
// after
let revision_from_user = revision_from_user.trim();
anyhow::ensure!(!revision_from_user.contains('\n'), "invalid revision spec: {revision_from_user:?}");
let contents = repo.load_revisions(vec![revision_from_user.to_owned()]).await?;
Defensive patterns

Strategy: validation

Validate before calling

fn sanitize_revision(spec: &str) -> anyhow::Result<&str> {
    let trimmed = spec.trim();
    anyhow::ensure!(
        !trimmed.is_empty() && !trimmed.contains('\n') && !trimmed.contains('\0'),
        "revision spec contains control characters: {spec:?}"
    );
    Ok(trimmed)
}

let revisions = revisions
    .iter()
    .map(|r| sanitize_revision(r).map(str::to_owned))
    .collect::<Result<Vec<_>>>()?;
let contents = repo.load_revisions(revisions).await?;

Try / catch

match repo.load_revisions(revisions).await {
    Err(e) if e.to_string().contains("cannot be passed to git cat-file") => {
        // bad input: sanitize the specs instead of retrying
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling a repository API that ends in load_revisions (batch-loading blob contents for multiple revisions, e.g. blame or project diff reading old file versions) where at least one revision string contains a newline. The offending spec is printed with Debug formatting ({revision:?}) so the message shows the embedded \n.

Common situations: Revision strings assembled from untrusted or loosely validated input: text pasted by a user (trailing newline never trimmed), refs parsed out of commit messages, or scripting bugs that embed newlines into ref names. Cheap sanitization is applied to URLs and paths but not to revision specs.

Related errors


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