## TL;DR
Feed reviewdog a clean unified diff or it chokes. The error means the diff piped into reviewdog has malformed or non-standard hunks. Re-generate the diff with plain `git diff` flags, strip binary files and external diff output, and the error goes away. It is a diff-format problem, not a reviewdog config problem.

## The query

```text
reviewdog: error: fail to parse diff: unexpected hunk header
```

## Use this when

- A CI job running reviewdog dies with "fail to parse diff"
- reviewdog works on most PRs but fails on ones with renames, merges, or binary files
- You piped a custom diff command into reviewdog and it errored

## Not for

- reviewdog "no filter matched for changed files"
- reviewdog annotation posting errors (permissions, auth)
- Writing new reviewdog errorformat rules

## Steps

### 1. Dump the exact diff your pipeline feeds reviewdog

Run the same diff command CI uses and save it:

```bash
git diff origin/main...HEAD > /tmp/pr.diff
head -c 2000 /tmp/pr.diff
```

Expected output: a normal unified diff starting with `diff --git` lines and `@@ -a,b +c,d @@` hunk headers.

### 2. Hunt for non-standard hunks

```bash
grep -n "^diff --git" /tmp/pr.diff | head
grep -c "^@@" /tmp/pr.diff
```

Suspects: `GIT binary patch` sections, `rename from/to` pairs with no hunks, combined merge diffs, or color codes. Expected output: you can see which file sections lack a proper `@@` header.

### 3. Regenerate with reviewdog-friendly flags

```bash
git diff --no-color --no-ext-diff -U3 origin/main...HEAD > /tmp/pr.diff
```

Expected output: no color codes, no external diff driver output, standard hunks only.

### 4. Exclude binary files from the reviewed diff

```bash
git diff --no-color -U3 origin/main...HEAD -- . ":!*.png" ":!*.jpg" ":!*.pdf" ":!*.woff2" > /tmp/pr.diff
```

Expected output: binary patch sections gone from the diff.

### 5. Re-run the reviewdog step against the cleaned diff

Point reviewdog at the cleaned file (or bake the flags from steps 3-4 into your diff-generation step) and re-run CI.

Expected output: reviewdog exits 0 and posts annotations instead of the parse error.

## Variant phrasings

### reviewdog fail to parse diff on PR

Same fix. If the diff comes from the GitHub API instead of git, fetch the raw unified diff with the diff media type so reviewdog gets clean hunks.

### unexpected hunk header from reviewdog in GitHub Actions

Check the diff-generation step first. A shallow fetch or a missing base ref produces truncated diffs. Fetch enough history or pass the base SHA explicitly.

## Why it happens

reviewdog parses the diff itself to map linter output onto file and line positions. Its parser expects strict unified format. Binary patches, merge combined diffs, external diff driver output, and colorized diffs all break that assumption, and it reports the first unparseable hunk header it hits.

## Edge cases

- Renamed files: reviewdog handles rename hunks, but only when similarity detection stayed intact. Renames detected as delete-plus-add on some versions confuse the parser.
- Huge diffs: parse errors can mask a timeout. Check stderr around the error for context lines.
- Version skew: older reviewdog releases had a stricter parser. Pin a recent version in CI before debugging the diff itself.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_4CL4pn4PxFU_RW2zBXM79g
