{"id":"ced83b143fe00a65","repo":"gohugoio/hugo","slug":"s-isn-t-a-key-of-map-type-s","errorCode":null,"errorMessage":"%s isn't a key of map type %s","messagePattern":"(.+?) isn't a key of map type (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/where.go","lineNumber":382,"sourceCode":"\t\treturn zero, fmt.Errorf(\"can't evaluate a nil pointer of type %s by a struct field or map key name %s\", typ, elemName)\n\t}\n\tobj = reflect.Indirect(obj)\n\tswitch obj.Kind() {\n\tcase reflect.Struct:\n\t\tft, ok := obj.Type().FieldByName(elemName)\n\t\tif ok {\n\t\t\tif ft.PkgPath != \"\" && !ft.Anonymous {\n\t\t\t\treturn zero, fmt.Errorf(\"%s is an unexported field of struct type %s\", elemName, typ)\n\t\t\t}\n\t\t\treturn obj.FieldByIndex(ft.Index), nil\n\t\t}\n\t\treturn zero, fmt.Errorf(\"%s isn't a field of struct type %s\", elemName, typ)\n\tcase reflect.Map:\n\t\tkv := reflect.ValueOf(elemName)\n\t\tif kv.Type().AssignableTo(obj.Type().Key()) {\n\t\t\treturn obj.MapIndex(kv), nil\n\t\t}\n\t\treturn zero, fmt.Errorf(\"%s isn't a key of map type %s\", elemName, typ)\n\t}\n\treturn zero, fmt.Errorf(\"%s is neither a struct field, a method nor a map element of type %s\", elemName, typ)\n}\n\n// parseWhereArgs parses the end arguments to the where function.  Return a\n// match value and an operator, if one is defined.\nfunc parseWhereArgs(args ...any) (mv reflect.Value, op string, err error) {\n\tswitch len(args) {\n\tcase 1:\n\t\tmv = reflect.ValueOf(args[0])\n\tcase 2:\n\t\tvar ok bool\n\t\tif op, ok = args[0].(string); !ok {\n\t\t\terr = errors.New(\"operator argument must be string type\")\n\t\t\treturn\n\t\t}\n\t\top = strings.TrimSpace(strings.ToLower(op))\n\t\tmv = reflect.ValueOf(args[1])","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/collections/where.go#L364-L400","documentation":"The element is a map, but the string key from the `where` path is not assignable to the map's key type (e.g. the map is keyed by int or another non-string type). Note this is a key-type mismatch, not a missing key — a missing string key on a string-keyed map simply yields a zero value.","triggerScenarios":"`where` over a collection of maps whose key type isn't string (e.g. `map[int]any` built via template logic or data with integer keys), so `reflect.ValueOf(elemName)` (a string) isn't AssignableTo the map's key type.","commonSituations":"YAML/TOML data that produced integer-keyed maps (e.g. `2024: ...` year keys) then filtered with a string path; programmatically built dicts with non-string keys passed to `where`.","solutions":["Restructure the data so maps are keyed by strings (quote numeric keys in YAML: `\"2024\":`).","Convert the collection into a slice of string-keyed maps before filtering.","If filtering by value rather than sub-key, iterate with `range` and compare manually."],"exampleFix":"# before (data/years.yaml -> map[int]...)\n2024:\n  title: A\n# after\n\"2024\":\n  title: A","handlingStrategy":"type-guard","validationCode":"{{ $first := index $dicts 0 }}\n{{ if isset $first \"category\" }}{{ $r = where $dicts \"category\" \"news\" }}{{ end }}","typeGuard":"{{/* guard: key present in map element */}}\n{{ define \"hasKey\" }}{{ return isset (index . 0) (index . 1) }}{{ end }}","tryCatchPattern":null,"preventionTips":["Check the key with isset on a sample element before filtering","Normalize data (e.g. in data files or front matter) so every map has the same keys","Mind key case: map keys are matched exactly for non-string-insensitive maps"],"tags":["hugo","templates","where","map","type-mismatch"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}