{"record":{"id":"4de1b9456d189742","repo":"aaif-goose/goose","slug":"git-diff-stat-returned-non-utf8-output-e","errorCode":null,"errorMessage":"git diff --stat returned non-UTF8 output: {e}","messagePattern":"git diff --stat returned non-UTF8 output: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/commands/review/handler.rs","lineNumber":447,"sourceCode":"        None => {\n            cmd.arg(\"HEAD\");\n        }\n    }\n    if !files.is_empty() {\n        cmd.arg(\"--\");\n        for f in files {\n            cmd.arg(f);\n        }\n    }\n    let out = cmd.output().context(\"git diff --stat failed\")?;\n    if !out.status.success() {\n        bail!(\n            \"git diff --stat failed: {}\",\n            String::from_utf8_lossy(&out.stderr)\n        );\n    }\n    String::from_utf8(out.stdout)\n        .map_err(|e| anyhow!(\"git diff --stat returned non-UTF8 output: {e}\"))\n}\n\n/// List untracked-but-not-ignored files in `repo_root`. Used to expose\n/// brand-new files to the review when no `--range` is given (default\n/// `git diff HEAD` would silently drop them).\nfn untracked_files(repo_root: &UntrackedRoot, files: &[String]) -> Result<Vec<String>> {\n    let mut cmd = untracked_git_command(repo_root)?;\n    cmd.args([\"ls-files\", \"--others\", \"--exclude-standard\"]);\n    if !files.is_empty() {\n        cmd.arg(\"--\");\n        for f in files {\n            cmd.arg(f);\n        }\n    }\n    let out = cmd.output().context(\"git ls-files failed\")?;\n    if !out.status.success() {\n        bail!(\n            \"git ls-files failed: {}\",","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/commands/review/handler.rs#L429-L465","documentation":"Identical guard to the diff collector but for the stat pass: `git diff --stat` output must decode as valid UTF-8 (String::from_utf8), and any non-UTF8 bytes — typically unescaped non-ASCII filenames — abort stat collection with this error.","triggerScenarios":"Running `goose review` when `git diff --stat` emits non-UTF8 bytes, e.g. non-ASCII filenames not quoted/escaped by git, or corrupted refs producing odd output.","commonSituations":"Same class as the diff variant: legacy filename encodings, mixed-OS teams, core.quotepath disabled by default in some setups.","solutions":["Set `git config core.quotepath true` so git escapes non-ASCII path bytes","Limit reviewed files to UTF-8-named paths via `--files`","Rename non-UTF8 filenames to valid UTF-8","Mark binary files in .gitattributes to keep stat output clean"],"exampleFix":"# before\ngoose review                    # --stat output non-UTF8 -> error\n\n# after\ngit config core.quotepath true\ngoose review","handlingStrategy":"validation","validationCode":"# Pre-check the stat pass specifically\ngit diff --stat HEAD | iconv -f UTF-8 -t UTF-8 > /dev/null 2>&1 \\\n  || echo 'git diff --stat output is not valid UTF-8: fix filenames or set core.quotepath=true'","typeGuard":null,"tryCatchPattern":"// Rust (own tooling): accept lossy decoding for stat output used only for display\nlet stat = String::from_utf8_lossy(&out.stdout).into_owned();","preventionTips":["Enable `git config core.quotepath true` in devcontainers","Scope reviews with --files to known text paths","Rename non-UTF8 files during repo onboarding"],"tags":["review","git","encoding","utf-8","filesystem"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}