dagger/dagger · error

parse hunk header %q: %w

Error message

parse hunk header %q: %w

What it means

When parsing a .rej (reject) file produced by `git apply`, each hunk header (e.g. `@@ -12,7 +12,8 @@`) is matched with rejectHunkHeader and its old start line parsed with strconv.Atoi. This error wraps a non-numeric or unexpected hunk-header line number.

Source

Thrown at core/directory.go:1958

// convertRejectToMarkers folds a git-apply .rej file into its target as
// git-style conflict markers: the surrounding content is left in place (the
// "workspace" side) and each rejected hunk's intended result is inserted at
// its recorded pre-image position (the "patch" side). Best-effort placement:
// the content has drifted from what the hunk expected — that is why it was
// rejected — so the markers flag the intent for a human or agent to resolve
// rather than reproduce the edit exactly.
func convertRejectToMarkers(targetPath, rejPath string) error {
	rejBytes, err := os.ReadFile(rejPath)
	if err != nil {
		return err
	}
	var hunks []rejectHunk
	for _, line := range strings.Split(string(rejBytes), "\n") {
		if m := rejectHunkHeader.FindStringSubmatch(line); m != nil {
			oldStart, err := strconv.Atoi(m[1])
			if err != nil {
				return fmt.Errorf("parse hunk header %q: %w", line, err)
			}
			hunks = append(hunks, rejectHunk{oldStart: oldStart})
			continue
		}
		if len(hunks) == 0 {
			continue // file header
		}
		h := &hunks[len(hunks)-1]
		if strings.HasPrefix(line, " ") || strings.HasPrefix(line, "+") {
			h.theirs = append(h.theirs, line[1:])
		}
	}
	if len(hunks) == 0 {
		return nil
	}

	var lines []string
	trailingNewline := true

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Open the .rej/.patch file and correct the malformed @@ hunk header so the old start line is an integer.
  2. Regenerate the patch/diff with `git diff` or `git apply` to replace the corrupted file.
  3. If the .rej came from your own tooling, fix the generator to emit standard unified-diff headers.
  4. Apply the rejected hunks manually and commit, bypassing automatic conflict-marker conversion.

Example fix

// before (malformed hunk header)
@@ -a,7 +b,8 @@
// after
@@ -12,7 +12,8 @@
Defensive patterns

Strategy: validation

Validate before calling

// validate hunk headers are well-formed before processing
const hunkRe = /^@@ -(\d+)(?:,\d+)? \+\d+(?:,\d+)? @@/;
for (const line of rejText.split("\n")) {
    if (line.startsWith("@@") && !hunkRe.test(line)) {
        throw new Error(`malformed hunk header: ${line}`);
    }
}

Type guard

function isWellFormedHunkHeader(line) {
  const m = /^@@ -(\d+)(?:,\d+)? \+\d+(?:,\d+)? @@/.exec(line);
  return m !== null && Number.isInteger(parseInt(m[1], 10));
}

Try / catch

try {
    dir.patch(diff)
} catch (err) {
    if (String(err).includes("parse hunk header")) {
        // regenerate the patch programmatically
        diff = regenerateDiff(baseDir, targetDir)
    } else throw err
}

Prevention

When it happens

Trigger: A malformed or hand-edited .rej/.patch whose hunk header looks like a match to rejectHunkHeader but whose line-number group is not a plain integer (e.g. `@@ -a,3 +b,4 @@`), or a regex false-positive on an unusual line.

Common situations: Patches edited by hand or by tooling that corrupted the @@ header; patches with nonstandard formats (unified diff variants); .rej files truncated or concatenated from multiple patches.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/1e7a11918c5f3db1. Report an issue: GitHub.