twpayne/chezmoi · error

%s: unknown format

Error message

%s: unknown format

What it means

UnmarshalFileData guesses the serialization format from the file's extension (via FormatsByExtension) and unmarshals accordingly. If the extension has no registered format (e.g. .txt, .md, .unknown), it refuses to guess and reports the full filename. This prevents silently mis-parsing data with the wrong decoder.

Source

Thrown at internal/chezmoi/format.go:72

	}

	// FormatsByExtension is a map of all Formats by extension.
	FormatsByExtension = map[string]Format{
		"jsonc": FormatJSONC,
		"json":  FormatJSON,
		"toml":  FormatTOML,
		"yaml":  FormatYAML,
		"yml":   FormatYAML,
	}
	FormatExtensions = slices.Sorted(maps.Keys(FormatsByExtension))
)

// UnmarshalFileData unmarshals data in the format guessed from filenameAbsPath.
func UnmarshalFileData(filenameAbsPath AbsPath, data []byte, value any) error {
	extension := strings.TrimPrefix(filenameAbsPath.Ext(), ".")
	format, ok := FormatsByExtension[extension]
	if !ok {
		return fmt.Errorf("%s: unknown format", filenameAbsPath)
	}
	return format.Unmarshal(data, value)
}

// Marshal implements Format.Marshal.
func (formatJSONC) Marshal(value any) ([]byte, error) {
	var builder strings.Builder
	encoder := json.NewEncoder(&builder)
	encoder.SetEscapeHTML(false)
	if err := encoder.Encode(value); err != nil {
		return nil, err
	}
	return hujson.Format([]byte(builder.String()))
}

// Name implements Format.Name.
func (formatJSONC) Name() string {
	return "jsonc"

View on GitHub (pinned to f901167e46)

Solutions

  1. Rename the file to use a supported extension (.json, .jsonc, .yaml, .yml, .toml)
  2. Move non-format files out of the source state directory so they are not parsed
  3. If the content is a supported format, fix the extension to match the actual content

Example fix

// before
mv config.yaml myconfig.conf   # chezmoi cannot guess format

// after
mv config.yaml myconfig.yaml
Defensive patterns

Strategy: validation

Validate before calling

supported := map[string]bool{"json":true,"jsonc":true,"yaml":true,"yml":true,"toml":true}
ext := strings.TrimPrefix(filepath.Ext(path), ".")
if !supported[ext] { return fmt.Errorf("%s: no format for extension", path) }

Try / catch

if err := chezmoi.UnmarshalFileData(path, data, &v); err != nil {
    if strings.Contains(err.Error(), "unknown format") {
        // pick a format explicitly or skip the file
    }
}

Prevention

When it happens

Trigger: Calling UnmarshalFileData (directly or via newSourceState) on a source file whose extension is not one of the supported format extensions (json, jsonc, yaml, yml, toml).

Common situations: Adding a source file with an unusual extension, a dotfile like '.foo' whose trimmed extension is empty, renaming a config file to a non-format extension.

Related errors


AI-assisted analysis of twpayne/chezmoi@f901167e46 (2026-09-01). Data as JSON: /api/errors/50bad3986066d5f4. Report an issue: GitHub.