golangci/golangci-lint · error
can't unmarshal config by viper (flags): %w
Error message
can't unmarshal config by viper (flags): %w
What it means
When viper cannot find any config file (viper.ConfigFileNotFoundError), the loader falls back to unmarshaling configuration from flags only into the settings struct. If viper.Unmarshal fails on the flag-only view, this error is returned and loading aborts.
Source
Thrown at pkg/config/base_loader.go:162
}
// find home directory for global config
if home, err := homedir.Dir(); err != nil {
l.log.Warnf("Can't get user's home directory: %v", err)
} else if !slices.Contains(searchPaths, home) {
searchPaths = append(searchPaths, home)
}
return searchPaths
}
func (l *BaseLoader) parseConfig() error {
if err := l.viper.ReadInConfig(); err != nil {
if _, ok := errors.AsType[viper.ConfigFileNotFoundError](err); ok {
// Load configuration from flags only.
err = l.viper.Unmarshal(l.cfg, customDecoderHook())
if err != nil {
return fmt.Errorf("can't unmarshal config by viper (flags): %w", err)
}
return nil
}
return fmt.Errorf("can't read viper config: %w", err)
}
err := l.setConfigDir()
if err != nil {
return err
}
// Load configuration from all sources (flags, file).
if err := l.viper.Unmarshal(l.cfg, customDecoderHook()); err != nil {
return fmt.Errorf("can't unmarshal config by viper (flags, file): %w", err)
}
View on GitHub (pinned to ed7a235d2d)
Solutions
- Check the wrapped error for the offending field and fix the flag value type/format
- Validate flags against `golangci-lint run --help` for expected value formats
- Remove or correct the recently added flag(s) to isolate the culprit
- Use a config file instead of many flags so values are type-checked in one place
Example fix
// before golangci-lint run --timeout=abc // after golangci-lint run --timeout=5m
Defensive patterns
Strategy: validation
Validate before calling
// Validate flag-only values before running
args := []string{"--timeout=5m", "--out-format=line-number"}
for _, a := range args {
if strings.Contains(a, "timeout=") {
if _, err := time.ParseDuration(strings.TrimPrefix(a, "--timeout=")); err != nil {
log.Fatalf("bad flag value: %s", a)
}
}
} Prevention
- Use correct value types for flags (durations as 5m, ints unquoted)
- Introduce new flags one at a time to isolate bad values
- Prefer a config file over long flag lists for complex settings
- Read the wrapped error: viper names the failing field
When it happens
Trigger: No config file found (or config search disabled) AND a flag-set value cannot be decoded into the config struct via the custom decoder hook — typically a flag value of the wrong type/format.
Common situations: Passing values with wrong types via flags (e.g. non-integer for a duration/int option); typo'd flag mapped onto a struct field with an incompatible type; malformed map/slice syntax in flag values.
Related errors
- can't unmarshal config by viper (flags, file): %w
- can't read viper config: %w
- the configuration contains invalid elements
- unsupported configuration format
- the configuration contains invalid elements
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/facef7c5e03e8432.
Report an issue: GitHub.