modernize atomictype analyzer breaks code when changes are split across files

Author: taran-pCreated Jul 14, 2026Updated Jul 31, 2026
Labelsbug

Welcome

  • Yes, I'm using a binary release within 2 latest releases. Only such installations are supported.
  • Yes, I've searched similar issues on GitHub and didn't find any.
  • Yes, I've read the typecheck section of the FAQ.
  • Yes, I've tried with the standalone linter if available (e.g., gocritic, go vet, etc.).
  • I agree to follow this project's Code of Conduct

How did you install golangci-lint?

go tool, Brew

Description of the problem

The atomictype analyzer in modernize has suggested fixes for a single issue that span multiple files. When using the --fix flag, fixes suggested for other files are appended or prepended onto of the file where the diagnostic was reported

Practically for modernize, this means in a.go where an int64 is turned into an atomic.Int64, any b.go .LoadInt64( will be added to the end of the a.go as .Load(, breaking the code.

Version of golangci-lint

golangci-lint has version 2.12.2 built with go1.26.5 from (unknown, modified: ?, mod sum: "h1:7+d1uY0bq1MU2UV3R5pW5Q7QWdcoq4naMRXM+gsJKrs=") on (unknown)

Configuration

bash
version: "2"
linters:
  default: none
  enable:
    - modernize

Go environment

bash
go version go1.26.5 darwin/arm64
AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/taran/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/taran/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/jm/8bq435r144zctj9gqy_k_qwh0000gn/T/go-build3173281144=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/taran/.claude/jobs/8c45bae8/tmp/mini-repro/go.mod'
GOMODCACHE='/Users/taran/go/pkg/mod'
GOOS='darwin'
GOPATH='/Users/taran/go'
GOPRIVATE='github.com/miniohq/*,github.com/taran-p/mineos'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.26.5/libexec'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/taran/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.26.5/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.26.5'
GOWORK=''
PKG_CONFIG='pkg-config'

Verbose output of running

bash
INFO golangci-lint has version 2.12.2 built with go1.26.2 from c0d3ddc on 2026-05-06T11:01:25Z 
INFO [config_reader] Config search paths: [./ /Users/taran/.claude/jobs/8c45bae8/tmp/mini-repro /Users/taran/.claude/jobs/8c45bae8/tmp /Users/taran/.claude/jobs/8c45bae8 /Users/taran/.claude/jobs /Users/taran/.claude /Users/taran /Users /] 
INFO [config_reader] Used config file .golangci.yml 
INFO [config_reader] Module name "minirepro"      
INFO [goenv] Read go env for 5.414958ms: map[string]string{"GOCACHE":"/Users/taran/Library/Caches/go-build", "GOROOT":"/opt/homebrew/Cellar/go/1.26.5/libexec"} 
INFO [lintersdb] Active 1 linters: [modernize]    
INFO [loader] Go packages loading at mode 8767 (compiled_files|deps|imports|types_sizes|exports_file|files|name) took 35.236667ms 
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 142.792µs 
INFO [linters_context/goanalysis] analyzers took 731.123µs with top 10 stages: newexpr: 380.999µs, inspect: 113.041µs, rangeint: 71.417µs, atomictypes: 43.042µs, stditerators: 30.792µs, typeindex: 24.125µs, mapsloop: 9.459µs, plusbuild: 9.042µs, omitzero: 6.541µs, slicescontains: 5.5µs 
INFO [runner] Applying suggested fixes            
WARN [runner] (fmt) formatting file /Users/taran/.claude/jobs/8c45bae8/tmp/mini-repro/test/a.go: 8:1: expected declaration, found '.' 
INFO [runner] fixer took 91.375µs with stages: all: 91.375µs 
INFO [runner] Issues before processing: 1, after processing: 0 
INFO [runner] Processors filtering stat (in/out): diff: 1/1, generated_file_filter: 1/1, exclusion_rules: 1/1, filename_unadjuster: 1/1, exclusion_paths: 1/1, fixer: 1/0, path_absoluter: 1/1, cgo: 1/1, invalid_issue: 1/1, path_relativity: 1/1, nolint_filter: 1/1 
INFO [runner] processing took 150µs with stages: fixer: 101.209µs, generated_file_filter: 24.583µs, nolint_filter: 18.292µs, sort_results: 2.084µs, path_relativity: 1.375µs, invalid_issue: 666ns, cgo: 375ns,path_shortener: 209ns, max_same_issues: 208ns, path_absoluter: 167ns, filename_unadjuster: 125ns, exclusion_paths: 125ns, exclusion_rules: 84ns, diff: 83ns, uniq_by_line: 83ns, max_from_linter: 83ns, path_prettifier: 83ns, source_code: 83ns, severity-rules: 42ns, max_per_file_from_linter: 41ns 
INFO [runner] linters took 8.259666ms with stages: goanalysis_metalinter: 8.069958ms 
0 issues.
INFO File cache stats: 1 entries of total size 41B 
INFO Memory: 2 samples, avg is 41.9MB, max is 44.0MB 
INFO Execution took 49.318875ms 

A minimal reproducible example or link to a public repository

File a.go

go
package test

type a struct {
	x int64
}

File b.go

go
package test

import "sync/atomic"

func b() int64 {
	var a a
	return atomic.LoadInt64(&a.x)
}

After golangci-lint run --fix, b.go is unchanged, a.go becomes

go
package test

import "sync/atomic"

type a struct {
	x atomic.Int64
}
.Load(

Validation

  • Yes, I've included all the information above (example, version, config, etc.).

Supporter