golangci/golangci-lint · error
formatting %s: %w
Error message
formatting %s: %w
What it means
After printing the transformed AST, writeNewFile runs the result through golang.org/x/tools/imports.Process, which parses, formats, and fixes up import statements. The 'formatting %s: %w' wrap means the printed AST text is not valid Go or the imports fix-up failed. The most common cause: after processFile drops const/var declarations and rewrites the package name, referenced imports or identifiers disappear, leaving invalid or unused-import state that Process cannot resolve into compilable source.
Source
Thrown at pkg/commands/internal/migrate/cloner/cloner.go:185
}
func writeNewFile(fset *token.FileSet, file *ast.File, srcPath, dstDir string) error {
var buf bytes.Buffer
buf.WriteString("// Code generated by pkg/commands/internal/migrate/cloner/cloner.go. DO NOT EDIT.\n\n")
err := printer.Fprint(&buf, fset, file)
if err != nil {
return fmt.Errorf("printing %s: %w", srcPath, err)
}
dstPath := filepath.Join(dstDir, filepath.Base(srcPath))
_ = os.MkdirAll(filepath.Dir(dstPath), os.ModePerm)
formatted, err := imports.Process(dstPath, buf.Bytes(), nil)
if err != nil {
return fmt.Errorf("formatting %s: %w", dstPath, err)
}
//nolint:gosec,mnd // The permission is right.
err = os.WriteFile(dstPath, formatted, 0o644)
if err != nil {
return fmt.Errorf("writing file %s: %w", dstPath, err)
}
return nil
}
View on GitHub (pinned to ed7a235d2d)
Solutions
- Read the wrapped imports.Process error — it reports the parse error location in the generated file
- Inspect the corresponding generated file under pkg/commands/internal/migrate/versiontwo to see the invalid source
- Check whether the source struct fields reference types/values that processFile strips (const/var declarations) and adjust processStructFields/convertType to keep or convert them
- Re-run the cloner after fixing pkg/config or the transformation rules
Example fix
// before (field type defined in a stripped const/var block)
type Config struct {
Mode config.Mode // type dropped by processFile -> unresolvable
}
// after: keep type declarations or convert the field
type Config struct {
Mode *string
} Defensive patterns
Strategy: validation
Validate before calling
// pre-check: attempt imports.Process on a copy before writing to disk
out, err := imports.Process(dstPath, buf.Bytes(), nil)
if err != nil {
log.Printf("generated source for %s is invalid: %v\n--- source ---\n%s", dstPath, err, buf.String())
return err
} Try / catch
if err := writeNewFile(fset, file, srcPath, dstDir); err != nil {
if strings.Contains(err.Error(), "formatting ") {
log.Printf("imports.Process failed for %s — inspect generated source under %s", srcPath, dstDir)
}
return err
} Prevention
- Ensure field types referenced in structs are not stripped by the const/var removal in processFile
- Run the cloner end-to-end and build the generated versiontwo package (go build ./pkg/commands/internal/migrate/versiontwo) as a smoke test
- Keep pkg/config imports resolvable under the new package name
- Fix the underlying config source first; the cloner copies real code, not a fixer
When it happens
Trigger: writeNewFile is called and imports.Process(dstPath, buf.Bytes(), nil) fails because the generated versiontwo package source does not parse — e.g. struct fields reference types that were removed with the const/var declarations, or the rewritten code contains references to deleted symbols.
Common situations: Adding new struct types to pkg/config whose fields use types defined in removed const/var blocks; renaming the package to versiontwo while code still references the old package-qualified identifiers; unresolvable imports in the copied file.
Related errors
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/0aacfcedf2dbaecb.
Report an issue: GitHub.