plandex-ai/plandex · error

error getting diff replacements: %v

Error message

error getting diff replacements: %v

What it means

After the updated file content is produced, buildStructuredEdits calls diff_pkg.GetDiffReplacements(originalFile, updated) to convert the whole-file diff into structured find/replace replacements. If that diff computation fails, the error is wrapped as "error getting diff replacements: %v" and reported through fileState.onBuildFileError, aborting the file build. This is a local diff-library failure, not an LLM failure.

Source

Thrown at app/server/model/plan/build_structured_edits.go:199

		Path:      filePath,
		NumTokens: 0,
		Finished:  true,
	}
	log.Printf("streaming build info for finished file %s\n", filePath)
	activePlan.Stream(shared.StreamMessage{
		Type:      shared.StreamMessageBuildInfo,
		BuildInfo: buildInfo,
	})
	time.Sleep(50 * time.Millisecond)

	// strip any blank lines from beginning/end of updated file
	updated = utils.StripAddedBlankLines(originalFile, updated)

	log.Printf("buildStructuredEdits - %s - getting diff replacements\n", filePath)
	replacements, err := diff_pkg.GetDiffReplacements(originalFile, updated)
	if err != nil {
		log.Printf("buildStructuredEdits - error getting diff replacements: %v\n", err)
		fileState.onBuildFileError(fmt.Errorf("error getting diff replacements: %v", err))
		return
	}
	log.Printf("buildStructuredEdits - %s - got %d replacements\n", filePath, len(replacements))

	for _, replacement := range replacements {
		replacement.Summary = strings.TrimSpace(desc)
	}

	res := db.PlanFileResult{
		TypeVersion:    1,
		OrgId:          fileState.plan.OrgId,
		PlanId:         fileState.plan.Id,
		PlanBuildId:    fileState.build.Id,
		ConvoMessageId: fileState.convoMessageId,
		Content:        "",
		Path:           filePath,
		Replacements:   replacements,
	}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Inspect the inner error; if it's an encoding/line-ending issue, normalize the updated content before diffing.
  2. Check that utils.StripAddedBlankLines(originalFile, updated) is not producing content the differ can't handle (e.g. empty string).
  3. Pin/upgrade the diff package version; check its issue tracker for known panics on large inputs.
  4. Add a fallback that emits a whole-file replacement when the diff cannot be computed.

Example fix

// before
replacements, err := diff_pkg.GetDiffReplacements(originalFile, updated)
if err != nil {
    fileState.onBuildFileError(fmt.Errorf("error getting diff replacements: %v", err))
    return
}
// after
replacements, err := diff_pkg.GetDiffReplacements(originalFile, updated)
if err != nil {
    log.Printf("diff failed (%v), falling back to whole-file replacement", err)
    replacements = []shared.Replacement{{Old: originalFile, New: updated}}
}
Defensive patterns

Strategy: fallback

Validate before calling

// Validate contents are diffable before calling
if updated == "" || !utf8.ValidString(updated) || !utf8.ValidString(originalFile) {
    return fmt.Errorf("cannot diff: invalid or empty content")
}

Try / catch

replacements, err := diff_pkg.GetDiffReplacements(originalFile, updated)
if err != nil {
    log.Printf("GetDiffReplacements failed: %v; using whole-file replacement", err)
    replacements = []db.Replacement{{Old: originalFile, New: updated, Summary: strings.TrimSpace(desc)}}
}

Prevention

When it happens

Trigger: diff_pkg.GetDiffReplacements(originalFile, updated) returns a non-nil error, typically when the diff library cannot compute a valid line-based diff between the original and updated file contents (e.g. pathological content, encoding issues, or an internal diff algorithm error).

Common situations: LLM output mangled the file encoding (invalid UTF-8, mixed line endings) so the differ chokes; very large files exceeding diff-library limits; a version change in the diff package changing GetDiffReplacements' failure modes.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/e93b2ab6a6c48d8d. Report an issue: GitHub.