{"record":{"id":"2b5a15654fe022aa","repo":"zed-industries/zed","slug":"unexpected-git-show-output-for-commit-output","errorCode":null,"errorMessage":"unexpected git-show output for {commit:?}: {output:?}","messagePattern":"unexpected git-show output for (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/git/src/repository.rs","lineNumber":1376,"sourceCode":"            cx.update(|cx| {\n                cx.path_for_auxiliary_executable(\"git\")\n                    .context(\"could not find git binary path\")\n                    .log_err()\n            })\n        } else {\n            None\n        };\n\n    let git = GitBinary::new(\n        git_binary_path.unwrap_or(PathBuf::from(\"git\")),\n        paths::home_dir().clone(),\n        paths::home_dir().join(\".git\"),\n        cx.background_executor().clone(),\n        true,\n    );\n\n    cx.background_spawn(async move {\n        let name = git\n            .run(&[\"config\", \"--global\", \"user.name\"])\n            .await\n            .log_err();\n        let email = git\n            .run(&[\"config\", \"--global\", \"user.email\"])\n            .await\n            .log_err();\n        GitCommitter { name, email }\n    })\n    .await\n}\n\nfn parse_remote_urls(stdout: &str) -> HashMap<String, String> {\n    let mut urls = HashMap::default();\n    for line in stdout.lines() {\n        if let Some((line, suffix)) = line.rsplit_once(\" (fetch)\")\n            && (suffix.is_empty() || suffix.starts_with(\" [\") && suffix.ends_with(']'))\n            && let Some((name, url)) = line.split_once(char::is_whitespace)","sourceCodeStart":1358,"sourceCodeEnd":1394,"githubUrl":"https://github.com/zed-industries/zed/blob/5a9b9558db01a6b906cec2fb70a797affdc58cdd/crates/git/src/repository.rs#L1358-L1394","documentation":"Commit details are parsed from `git show --no-patch --format=%H%x00%B%x00%at%x00%ae%x00%an%x00 <commit>`; the code splits stdout on NUL and requires exactly 6 fields (sha, body, timestamp, email, name, trailing empty). Any other field count bails with the whole output in Debug form. Since the format always emits five NULs, a count != 6 means the output itself was perturbed — most plausibly NUL bytes inside the commit message body.","triggerScenarios":"Loading commit details for a commit whose message body contains NUL bytes (created via plumbing or forged objects), output polluted by replace refs/grafts, or a git wrapper emitting extra content to stdout.","commonSituations":"Repositories containing pathological hand-crafted commits, `git replace` refs in play, or tools wrapping git that prepend banners to stdout.","solutions":["Reproduce: git show --no-patch --format='%H%x00%B%x00%at%x00%ae%x00%an%x00' <commit> | tr '\\0' '\\n' and count the fields","Inspect the commit with `git cat-file commit <sha>` for NUL bytes or odd header content","Check `git replace -l` and info/grafts and remove any perturbing refs","If the commit is genuinely malformed, rewrite/redact it (filter-repo) or skip details for it"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let fields = output.split('\\0').collect::<Vec<_>>();\nif fields.len() != 6 {\n    // dump the raw stdout for diagnosis instead of bubbling the bail\n    log::warn!(\"unexpected git-show fields: {fields:?}\");\n}","typeGuard":"fn is_parseable_show_output(output: &str) -> bool {\n    output.split('\\0').count() == 6\n}","tryCatchPattern":"match details(commit).await {\n    Ok(d) => Ok(d),\n    Err(e) if e.to_string().contains(\"unexpected git-show output\") => { /* fall back to log --format=1 parsing */ }\n    Err(e) => Err(e),\n}","preventionTips":["Keep stdout clean: no git wrappers/banners, check `git replace -l` in odd repos","Reject NUL bytes in commit messages at creation time (hooks) so show output stays parseable"],"tags":["git","show","parse","commit","output-format"],"backgroundTag":"git-output-parse-error","analyzedSha":"5a9b9558db01a6b906cec2fb70a797affdc58cdd","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}