{"record":{"id":"4fad1334cb52b5a7","repo":"twpayne/chezmoi","slug":"expected-a-string-got-a-t-4fad13","errorCode":null,"errorMessage":"expected a []string, got a %T","messagePattern":"expected a \\[\\]string, got a %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/entrytypeset.go","lineNumber":355,"sourceCode":"\treturn strings.Join(entryTypeStrs, \",\")\n}\n\n// Type implements github.com/spf13/pflag.Value.Type.\nfunc (s *EntryTypeSet) Type() string {\n\treturn \"types\"\n}\n\n// StringSliceToEntryTypeSetHookFunc is a\n// github.com/go-viper/mapstructure/v2.DecodeHookFunc that parses an\n// EntryTypeSet from a []string.\nfunc StringSliceToEntryTypeSetHookFunc() mapstructure.DecodeHookFunc {\n\treturn func(from, to reflect.Type, data any) (any, error) {\n\t\tif to != reflect.TypeFor[EntryTypeSet]() {\n\t\t\treturn data, nil\n\t\t}\n\t\telemsAny, ok := data.([]any)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"expected a []string, got a %T\", data)\n\t\t}\n\t\telemStrs := make([]string, len(elemsAny))\n\t\tfor i, elemAny := range elemsAny {\n\t\t\telemStr, ok := elemAny.(string)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"expected a []string, got a %T element\", elemAny)\n\t\t\t}\n\t\t\telemStrs[i] = elemStr\n\t\t}\n\t\ts := NewEntryTypeSet(EntryTypesNone)\n\t\tif err := s.SetSlice(elemStrs); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn s, nil\n\t}\n}\n\n// EntryTypeSetFlagCompletionFunc completes EntryTypeSet flags.","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/entrytypeset.go#L337-L373","documentation":"This map-to-EntryTypeSet decode hook expects JSON/YAML config data to be a []any that it will narrow to strings. If the whole value is not a []any (e.g. a string, map, or bool), the hook fails with this message showing the actual Go type. It exists to convert list-style entry type config values into EntryTypeSet.","triggerScenarios":"A config value that should be a list of entry type strings (e.g. in .chezmoi.toml or a decode hook target) is instead a scalar or object — a single quoted string rather than an array.","commonSituations":"Writing mode = \"file\" instead of mode = [\"file\"] in config, YAML collapsing a one-element list incorrectly, or passing the wrong field type when programmatically building config.","solutions":["Wrap the value in a list: use [\"file\"] instead of \"file\"","Check the config schema for the field and match the expected []string type","If building data programmatically, pass []any{...} of strings into the decode path"],"exampleFix":"// before (config)\nmode = \"file\"\n\n// after\nmode = [\"file\"]","handlingStrategy":"type-guard","validationCode":"if _, ok := value.([]any); !ok {\n    return fmt.Errorf(\"entry type config must be a list\")\n}","typeGuard":"func isStringSlice(v any) bool {\n    elems, ok := v.([]any)\n    if !ok { return false }\n    for _, e := range elems {\n        if _, ok := e.(string); !ok { return false }\n    }\n    return true\n}","tryCatchPattern":"var out EntryTypeSet\nif err := decode(data, &out); err != nil {\n    if strings.Contains(err.Error(), \"expected a []string\") {\n        // wrap scalar into []any{scalar} and retry\n    }\n}","preventionTips":["Always author entry type config values as lists, even single values","Quote all elements in YAML/TOML","Add schema validation to generated config files"],"tags":["go","type-mismatch","decode-hook","configuration"],"backgroundTag":"expected-array-got-scalar","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}