micro-editor/micro · info

no next diff hunk

Error message

no next diff hunk

What it means

Returned by (*Buffer).FindNextDiffLine (internal/buffer/buffer.go:1447) when the scan walks past the end of the buffer (curLine < 0 or > LinesNum()) without the diff status changing to a new hunk. In other words: from startLine in the given direction there is no further changed/unchanged boundary — you're already at the last (or first) diff hunk. It is a search-exhausted sentinel, not a fault.

Source

Thrown at internal/buffer/buffer.go:1447

// FindNextDiffLine returns the line number of the next block of diffs.
// If `startLine` is already in a block of diffs, lines in that block are skipped.
func (b *Buffer) FindNextDiffLine(startLine int, forward bool) (int, error) {
	if b.diff == nil {
		return 0, errors.New("no diff data")
	}
	startStatus, ok := b.diff[startLine]
	if !ok {
		startStatus = DSUnchanged
	}
	curLine := startLine
	for {
		curStatus, ok := b.diff[curLine]
		if !ok {
			curStatus = DSUnchanged
		}
		if curLine < 0 || curLine > b.LinesNum() {
			return 0, errors.New("no next diff hunk")
		}
		if curStatus != startStatus {
			if startStatus != DSUnchanged && curStatus == DSUnchanged {
				// Skip over the block of unchanged text
				startStatus = DSUnchanged
			} else {
				return curLine, nil
			}
		}
		if forward {
			curLine++
		} else {
			curLine--
		}
	}
}

// SearchMatch returns true if the given location is within a match of the last search.

View on GitHub (pinned to 1c8b82b32e)

Solutions

  1. Treat it as 'no more hunks': reverse direction (use PrevDiff) or jump back with > goto / undoline
  2. Re-run > diff to refresh hunk positions if you believe changes exist beyond the cursor (stale diff state after edits)
  3. In plugins, break the loop on this error rather than retrying

Example fix

// before
for {
    l, err := h.Buf.FindNextDiffLine(cur, true)
    cur = l // ignores err, loops forever at EOF
}

// after
for {
    l, err := h.Buf.FindNextDiffLine(cur, true)
    if err != nil { break } // no next diff hunk -> done
    cur = l
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Bound the search yourself so exhaustion is expected, not exceptional
to := h.Buf.LinesNum()
if forward && cur >= to-1 { /* nothing ahead: skip the call */ }
if !forward && cur <= 0 { /* nothing behind: skip the call */ }
dl, err := h.Buf.FindNextDiffLine(cur, forward)

Try / catch

for {
    l, err := h.Buf.FindNextDiffLine(cur, true)
    if err != nil {
        if err.Error() == "no next diff hunk" {
            break // sentinel: reached last hunk in this direction — stop cleanly
        }
        return err // unexpected
    }
    cur = l
}

Prevention

When it happens

Trigger: Cursor sits in/below the final changed hunk and NextDiff is invoked (forward scan hits EOF); or cursor is above the first hunk and PrevDiff is invoked (backward scan hits BOF). Emitted by the NextDiff/PrevDiff actions in internal/action/actions.go.

Common situations: Repeatedly pressing the next-diff binding to review changes and running one press past the last hunk; macros that loop diffs without an exit condition.

Related errors


AI-assisted analysis of micro-editor/micro@1c8b82b32e (2026-08-15). Data as JSON: /api/errors/2e8bb1f344963792. Report an issue: GitHub.