{"record":{"id":"60cd58d1b16933c6","repo":"golangci/golangci-lint","slug":"write-file-s-w","errorCode":null,"errorMessage":"write file %s: %w","messagePattern":"write file (.+?): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/internal/imports.go","lineNumber":39,"sourceCode":"\nfunc (b Builder) updatePluginsFile() error {\n\timportsDest := filepath.Join(b.repo, \"cmd\", \"golangci-lint\", \"plugins.go\")\n\n\tinfo, err := os.Stat(importsDest)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"file %s not found: %w\", importsDest, err)\n\t}\n\n\tsource, err := generateImports(b.cfg)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"generate imports: %w\", err)\n\t}\n\n\tb.log.Infof(\"generated imports info %s:\\n%s\\n\", importsDest, source)\n\n\terr = os.WriteFile(filepath.Clean(importsDest), source, info.Mode())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"write file %s: %w\", importsDest, err)\n\t}\n\n\treturn nil\n}\n\nfunc generateImports(cfg *Configuration) ([]byte, error) {\n\timpTmpl, err := template.New(\"plugins.go\").Parse(importsTemplate)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parse template: %w\", err)\n\t}\n\n\tvar imps []string\n\tfor _, plugin := range cfg.Plugins {\n\t\timps = append(imps, plugin.Import)\n\t}\n\n\tbuf := &bytes.Buffer{}\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/commands/internal/imports.go#L21-L57","documentation":"After regenerating plugins.go source, updatePluginsFile writes it back with os.WriteFile preserving the original file mode captured by the earlier Stat. If the write fails (permissions, read-only filesystem, disk full), the error wraps the cause as 'write file <path>: ...'.","triggerScenarios":"os.WriteFile(importsDest) fails during Build — typically EACCES on cmd/golangci-lint/plugins.go, a read-only checkout, or the directory removed between Stat and Write.","commonSituations":"Building inside a container with a read-only mounted repo; file owned by root or another UID; disk full; generated file made immutable.","solutions":["Make cmd/golangci-lint/plugins.go writable (chmod u+w or chown to the build user)","Run the build outside read-only mounts or copy the repo to a writable location first","Fix container UID/ownership so the build user can write the checkout","Check disk space and that cmd/golangci-lint/ still exists"],"exampleFix":"// before\n$ golangci-lint custom   # fails: write file ...: permission denied\n// after\n$ chmod u+w cmd/golangci-lint/plugins.go && golangci-lint custom","handlingStrategy":"validation","validationCode":"p := filepath.Join(repo, \"cmd\", \"golangci-lint\", \"plugins.go\")\nif info, err := os.Stat(p); err == nil && info.Mode().Perm()&0o200 == 0 {\n\tos.Chmod(p, info.Mode()|0o200)\n}","typeGuard":null,"tryCatchPattern":"err := builder.Build(ctx)\nif err != nil && strings.Contains(err.Error(), \"write file \"+importsDest) {\n\tvar pe *fs.PathError\n\tif errors.As(err, &pe) && errors.Is(pe.Err, os.ErrPermission) {\n\t\tos.Chmod(importsDest, 0o644) // fix and retry\n\t}\n}","preventionTips":["Run builds on a writable checkout, not read-only mounts","Chown/chmod the repo to the build user in CI containers","Check disk space before long builds","Never make generated files immutable (chattr +i)"],"tags":["filesystem","permissions","go","build"],"backgroundTag":"permission-denied","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}