twpayne/chezmoi · error

expected a []string, got a %T element

Error message

expected a []string, got a %T element

What it means

Same decode hook as the array-level check, but this fires per element: the data was a []any, yet one of its elements is not a string. The error reports the element's actual Go type so the offending config value can be identified.

Source

Thrown at internal/chezmoi/entrytypeset.go:361

}

// StringSliceToEntryTypeSetHookFunc is a
// github.com/go-viper/mapstructure/v2.DecodeHookFunc that parses an
// EntryTypeSet from a []string.
func StringSliceToEntryTypeSetHookFunc() mapstructure.DecodeHookFunc {
	return func(from, to reflect.Type, data any) (any, error) {
		if to != reflect.TypeFor[EntryTypeSet]() {
			return data, nil
		}
		elemsAny, ok := data.([]any)
		if !ok {
			return nil, fmt.Errorf("expected a []string, got a %T", data)
		}
		elemStrs := make([]string, len(elemsAny))
		for i, elemAny := range elemsAny {
			elemStr, ok := elemAny.(string)
			if !ok {
				return nil, fmt.Errorf("expected a []string, got a %T element", elemAny)
			}
			elemStrs[i] = elemStr
		}
		s := NewEntryTypeSet(EntryTypesNone)
		if err := s.SetSlice(elemStrs); err != nil {
			return nil, err
		}
		return s, nil
	}
}

// EntryTypeSetFlagCompletionFunc completes EntryTypeSet flags.
func EntryTypeSetFlagCompletionFunc(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
	var completions []string
	entryTypes := strings.Split(toComplete, ",")
	lastEntryType := entryTypes[len(entryTypes)-1]
	var prefix string
	if len(entryTypes) > 0 {

View on GitHub (pinned to f901167e46)

Solutions

  1. Quote the element so it parses as a string (e.g. ["file"] not [file] where file resolves oddly)
  2. Flatten accidental nested lists
  3. Inspect the reported %T type to locate the bad element and correct it

Example fix

// before
mode = [file, dir]

// after
mode = ["file", "dir"]
Defensive patterns

Strategy: type-guard

Validate before calling

for i, e := range elems {
    if _, ok := e.(string); !ok {
        return fmt.Errorf("element %d is %T, want string", i, e)
    }
}

Type guard

func isStringElem(v any) bool {
    _, ok := v.(string)
    return ok
}

Try / catch

if err := decode(data, &out); err != nil {
    if strings.Contains(err.Error(), "got a %T element") || strings.Contains(err.Error(), " element") {
        // coerce numeric/bool elements to strings and retry
    }
}

Prevention

When it happens

Trigger: An entry type list contains a non-string element, e.g. mode = [123], [true], or a nested list [["file"]] resulting from YAML/JSON parsing.

Common situations: Unquoted numeric-looking type values in TOML/YAML, accidental nesting of lists, template or script generating config with wrong element types.

Related errors


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