spf13/viper · error
config type could not be determined for %s
Error message
config type could not be determined for %s
What it means
Returned by writeConfig (viper.go:1743-1756) when the derived configType is empty. configType comes from the filename extension (if it has one and is not the whole basename), otherwise from v.configType (set via SetConfigType). If both are empty, Viper cannot pick an encoder.
Source
Thrown at viper.go:1755
if alreadyExists && err == nil {
return ConfigFileAlreadyExistsError(filename)
}
return v.writeConfig(filename, false)
}
func (v *Viper) writeConfig(filename string, force bool) error {
v.logger.Info("attempting to write configuration to file")
var configType string
ext := filepath.Ext(filename)
if ext != "" && ext != filepath.Base(filename) {
configType = ext[1:]
} else {
configType = v.configType
}
if configType == "" {
return fmt.Errorf("config type could not be determined for %s", filename)
}
if !slices.Contains(SupportedExts, configType) {
return UnsupportedConfigError(configType)
}
if v.config == nil {
v.config = make(map[string]any)
}
flags := os.O_CREATE | os.O_TRUNC | os.O_WRONLY
if !force {
flags |= os.O_EXCL
}
f, err := v.fs.OpenFile(filename, flags, v.configPermissions)
if err != nil {
return err
}
defer f.Close()
View on GitHub (pinned to 528f7416c4)
Solutions
- Call v.SetConfigType("yaml") (or json/toml/env) before WriteConfig/WriteConfigAs.
- Write to a filename with a recognized extension (e.g. 'app.yaml') so the type is inferred from the extension.
- For dotfiles or extensionless names, SetConfigType is mandatory — there is no fallback.
Example fix
// before
v := New()
v.SetConfigName("app")
_ = v.WriteConfigAs("/etc/myapp/config") // -> config type could not be determined for /etc/myapp/config
// after
v.SetConfigType("yaml")
_ = v.WriteConfigAs("/etc/myapp/config")
// or: _ = v.WriteConfigAs("/etc/myapp/config.yaml") Defensive patterns
Strategy: validation
Validate before calling
// Before WriteConfig/WriteConfigAs, ensure a type is resolvable.
func ensureWriteType(v *viper.Viper, filename string) error {
ext := filepath.Ext(filename)
hasExt := ext != "" && ext != filepath.Base(filename)
if hasExt { return nil }
if v.GetConfigType() != "" { return nil }
return errors.New("no config type: call SetConfigType or use an extension")
}
if err := ensureWriteType(v, "/etc/myapp/config"); err != nil {
v.SetConfigType("yaml")
}
v.WriteConfigAs("/etc/myapp/config") Try / catch
if err := v.WriteConfigAs(path); err != nil {
if strings.Contains(err.Error(), "config type could not be determined") {
v.SetConfigType("yaml")
err = v.WriteConfigAs(path)
}
} Prevention
- Always write config files with a recognized extension.
- If you must use an extensionless/dotfile name, call SetConfigType unconditionally.
- Remember filepath.Ext('.myapp') returns '' — dotfiles look extensionless to Viper.
When it happens
Trigger: Calling v.WriteConfigAs("configfile") with a path that has no extension and no prior SetConfigType; v.WriteConfig() where the resolved config file is extensionless and SetConfigType was never called.
Common situations: Writing generated config to an extensionless path (e.g. /run/myapp/current); renaming to a dotfile like '.myapp' (filepath.Ext returns ''); building a config bootstrapper that picks an arbitrary filename.
Related errors
- encoder not found for this format
- missing configuration for 'configPath'
- cannot decode configuration: unable to determine config type
AI-assisted analysis of spf13/viper@528f7416c4 (2026-08-04).
Data as JSON: /data/errors/c5db24d314178b23.json.
Report an issue: GitHub.