twpayne/chezmoi · error

%s: invalid format-indent

Error message

%s: invalid format-indent

What it means

The format-indent template option controls JSON encoder indentation and must match formatIndentRx (valid indent strings like spaces/tabs). An invalid value for format-indent aborts template parsing with '<value>: invalid format-indent'.

Source

Thrown at internal/chezmoi/template.go:50

	Funcs          template.FuncMap
	FormatIndent   string
	LeftDelimiter  string
	LineEnding     string
	RightDelimiter string
	Options        []string
}

// ParseTemplate parses a template named name from data with the given funcs and
// templateOptions.
func ParseTemplate(name string, data []byte, options TemplateOptions) (*Template, error) {
	contents, err := options.parseAndRemoveDirectives(data)
	if err != nil {
		return nil, err
	}
	funcs := options.Funcs
	if options.FormatIndent != "" {
		if !formatIndentRx.MatchString(options.FormatIndent) {
			return nil, fmt.Errorf("%s: invalid format-indent", options.FormatIndent)
		}
		funcs = maps.Clone(funcs)
		funcs["toJson"] = func(data any) string {
			var builder strings.Builder
			encoder := json.NewEncoder(&builder)
			encoder.SetIndent("", options.FormatIndent)
			if err := encoder.Encode(data); err != nil {
				panic(err)
			}
			return builder.String()
		}
		funcs["toToml"] = func(data any) string {
			var builder strings.Builder
			encoder := toml.NewEncoder(&builder)
			encoder.Indent = options.FormatIndent
			if err := encoder.Encode(data); err != nil {
				panic(err)
			}

View on GitHub (pinned to f901167e46)

Solutions

  1. Use a supported format-indent value such as " " (two spaces) or "\t" (tab)
  2. If you want numeric indentation, use the format-indent-width directive instead
  3. Check the regex-accepted characters: plain spaces or tabs only, no other characters

Example fix

// before in template
{{- /* format-indent: "\t  " */ -}}{{ toJson . }}
// after
{{- /* format-indent: "\t" */ -}}{{ toJson . }}
Defensive patterns

Strategy: validation

Validate before calling

// validate format-indent before parsing templates
var formatIndentRx = regexp.MustCompile(`^( |\t)+$`)
if options.FormatIndent != "" && !formatIndentRx.MatchString(options.FormatIndent) {
  return fmt.Errorf("invalid format-indent %q: use only spaces or tabs", options.FormatIndent)
}

Type guard

func isValidFormatIndent(s string) bool { return s == "" || formatIndentRx.MatchString(s) }

Try / catch

tmpl, err := ParseTemplate(...)
if err != nil && strings.Contains(err.Error(), "invalid format-indent") {
  return fmt.Errorf("fix the format-indent directive (spaces/tabs only): %w", err)
}

Prevention

When it happens

Trigger: A template directive like {{- /* format-indent: "\t " odd value */ -}} whose value fails the formatIndentRx validation during ParseTemplate.

Common situations: Typo or exotic whitespace (multi-char combos, control characters) in the format-indent directive; copying an example with an unsupported indent value; confusion with format-indent-width which takes a number.

Related errors


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