{"record":{"id":"5aed7e67b92d0fde","repo":"golangci/golangci-lint","slug":"q-suggests-invalid-fix-pos-v-end-v","errorCode":null,"errorMessage":"%q suggests invalid fix: pos (%v) > end (%v)","messagePattern":"%q suggests invalid fix: pos \\((.+?)\\) > end \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/result/processors/fixer.go","lineNumber":106,"sourceCode":"\n\tfor i := range issues {\n\t\tissue := issues[i]\n\n\t\tif slices.Contains(formatters, issue.FromLinter) {\n\t\t\ttoBeFormattedFiles[issue.FilePath()] = struct{}{}\n\t\t\tcontinue\n\t\t}\n\n\t\tif issue.SuggestedFixes == nil || skipNoTextEdit(issue) {\n\t\t\tnotFixableIssues = append(notFixableIssues, issue)\n\t\t\tcontinue\n\t\t}\n\n\t\tfor _, sf := range issue.SuggestedFixes {\n\t\t\tfor _, edit := range sf.TextEdits {\n\t\t\t\tstart, end := edit.Pos, edit.End\n\t\t\t\tif start > end {\n\t\t\t\t\treturn nil, fmt.Errorf(\"%q suggests invalid fix: pos (%v) > end (%v)\",\n\t\t\t\t\t\tissue.FromLinter, edit.Pos, edit.End)\n\t\t\t\t}\n\n\t\t\t\tedit := diff.Edit{\n\t\t\t\t\tStart: int(start),\n\t\t\t\t\tEnd:   int(end),\n\t\t\t\t\tNew:   string(edit.NewText),\n\t\t\t\t}\n\n\t\t\t\tif _, ok := editsByLinter[issue.FilePath()]; !ok {\n\t\t\t\t\teditsByLinter[issue.FilePath()] = make(map[string][]diff.Edit)\n\t\t\t\t}\n\n\t\t\t\teditsByLinter[issue.FilePath()][issue.FromLinter] = append(editsByLinter[issue.FilePath()][issue.FromLinter], edit)\n\t\t\t}\n\t\t}\n\t}\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/result/processors/fixer.go#L88-L124","documentation":"The fixer applies SuggestedFixes from linters, and each text edit must have Pos <= End. When a linter emits a suggested fix whose start position is after its end position, the fixer rejects the whole run's fixes with this error naming the linter. It guards against corrupting files with inverted edit ranges.","triggerScenarios":"process iterates issue.SuggestedFixes and encounters a TextEdit where edit.Pos > edit.End — produced by a buggy linter or an analyzer working with stale/incorrect position information.","commonSituations":"A custom or third-party linter computing token positions off-by-one; using a linter version incompatible with the golangci-lint go/analysis version; fixes generated from cached/rewritten file positions after edits.","solutions":["Update (or pin) the offending linter named in the error to a version with fixed position computation","Disable the linter's fixer for that linter (e.g. run without --fix or exclude the linter) until fixed","Report the bug to the linter maintainer with the failing file/linter name","Verify file/position data isn't being transformed between analysis and fixing in custom plugins"],"exampleFix":"// before (custom linter)\nedit := analysis.TextEdit{Pos: end, End: start}\n// after\nif start > end { start, end = end, start }\nedit := analysis.TextEdit{Pos: start, End: end}","handlingStrategy":"validation","validationCode":"// Go: sanity-check text edits before emitting a SuggestedFix from a custom linter\nfunc validEdit(e analysis.TextEdit) bool { return e.Pos <= e.End }\nif !validEdit(edit) { return nil, fmt.Errorf(\"invalid edit range %d..%d\", edit.Pos, edit.End) }","typeGuard":null,"tryCatchPattern":"fixed, err := fixer.Process(issues)\nif err != nil {\n    if strings.Contains(err.Error(), \"suggests invalid fix\") {\n        log.Fatalf(\"linter emitted bad fix: %v\", err)\n    }\n    return err\n}","preventionTips":["Keep linter versions in sync with the golangci-lint go/analysis version","Test custom analyzers' suggested fixes against go/analysis's own sanity checks","Avoid mutating positions (e.g. via token.File offsets) after prior edits"],"tags":["suggested-fixes","positions","linter-bug"],"backgroundTag":"invalid-suggested-fix-range","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}