{"record":{"id":"670ef1510b57a7c2","repo":"golangci/golangci-lint","slug":"saving-configuration-file-w","errorCode":null,"errorMessage":"saving configuration file: %w","messagePattern":"saving configuration file: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/migrate.go","lineNumber":123,"sourceCode":"\t}\n\n\tif !strings.EqualFold(filepath.Ext(srcPath), ext) {\n\t\tdefer func() {\n\t\t\t_ = os.RemoveAll(srcPath)\n\t\t}()\n\t}\n\n\tif c.cfg.Run.Timeout != 0 {\n\t\tc.log.Warnf(\"The configuration `run.timeout` is ignored. By default, in v2, the timeout is disabled.\")\n\t}\n\n\tnewCfg := migrate.ToConfig(c.cfg)\n\n\tdstPath := strings.TrimSuffix(srcPath, filepath.Ext(srcPath)) + ext\n\n\terr = saveNewConfiguration(newCfg, dstPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"saving configuration file: %w\", err)\n\t}\n\n\tc.log.Infof(\"Migration done: %s\", dstPath)\n\n\tcallForAction(c.cmd)\n\n\treturn nil\n}\n\nfunc (c *migrateCommand) preRunE(cmd *cobra.Command, _ []string) error {\n\tswitch strings.ToLower(c.opts.format) {\n\tcase \"\", \"yml\", \"yaml\", \"toml\", \"json\":\n\t\t// Valid format.\n\tdefault:\n\t\treturn fmt.Errorf(\"unsupported format: %s\", c.opts.format)\n\t}\n\n\tif c.cfg.Version != \"\" {","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/commands/migrate.go#L105-L141","documentation":"This error wraps any failure that occurs while writing the migrated (v2) configuration file to disk during `golangci-lint migrate`. The command converts a v1 config into the new format via `saveNewConfiguration`; if that helper fails (file creation, marshaling, or write error), it is wrapped with this message and returned to the caller. It is a shell error — the root cause is always the wrapped inner error.","triggerScenarios":"Running `golangci-lint migrate` when the destination path (source path with extension replaced) is not writable, e.g. the directory does not exist, permissions deny writing, the target file is locked/read-only, or serializing the new config to the requested format (yml/toml/json) fails.","commonSituations":"Running migrate in a read-only checkout or CI workspace; migrating a config in a directory the user cannot write to; a read-only mounted volume; the output file being open in an editor with a lock; an unsupported/invalid format value that passes validation but fails serialization.","solutions":["Read the wrapped error after this message to find the root cause (e.g. 'permission denied', 'no such file or directory').","Ensure the migration output directory exists and is writable by the current user (chmod/chown or run from a writable copy).","Copy the project (or just the config) to a writable location and run migrate there.","If the file is locked, close the program holding it, then rerun migrate.","Check disk space with `df -h` if the error indicates a full filesystem."],"exampleFix":"// before\ngolangci-lint migrate   # run in a read-only CI checkout\n// after\nchmod u+w .golangci.yml && golangci-lint migrate\n# or run in a writable copy of the repo","handlingStrategy":"try-catch","validationCode":"// Go: verify the migration destination is writable before running migrate\ndst := strings.TrimSuffix(src, filepath.Ext(src)) + \".yml\"\nif f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE, 0o644); err != nil {\n    return fmt.Errorf(\"destination %s not writable: %w\", dst, err)\n} else {\n    f.Close()\n}","typeGuard":null,"tryCatchPattern":"if err := saveNewConfiguration(newCfg, dstPath); err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) {\n        log.Printf(\"write failed at %s: %v (op=%s)\", pe.Path, pe.Err, pe.Op)\n    }\n    return fmt.Errorf(\"saving configuration file: %w\", err)\n}","preventionTips":["Run migrate from a writable working copy, never a read-only mount.","Ensure the output directory exists before migrating.","Avoid migrating configs inside locked editors or file-sync tools holding locks.","Check disk space in CI runners before running migrations."],"tags":["go","cli","filesystem","config-migration"],"backgroundTag":"file-write-permission-denied","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}