{"id":"134cf20b1d295f3a","repo":"gohugoio/hugo","slug":"destination-must-be-a-map-got-t","errorCode":null,"errorMessage":"destination must be a map, got %T","messagePattern":"destination must be a map, got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/merge.go","lineNumber":53,"sourceCode":"\tvar err error\n\tresult := params[len(params)-1]\n\n\tfor i := len(params) - 2; i >= 0; i-- {\n\t\tresult, err = ns.merge(params[i], result)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// merge creates a copy of dst and merges src into it.\nfunc (ns *Namespace) merge(src, dst any) (any, error) {\n\tvdst, vsrc := reflect.ValueOf(dst), reflect.ValueOf(src)\n\n\tif vdst.Kind() != reflect.Map {\n\t\treturn nil, fmt.Errorf(\"destination must be a map, got %T\", dst)\n\t}\n\n\tif !hreflect.IsTruthfulValue(vsrc) {\n\t\treturn dst, nil\n\t}\n\n\tif vsrc.Kind() != reflect.Map {\n\t\treturn nil, fmt.Errorf(\"source must be a map, got %T\", src)\n\t}\n\n\tif vsrc.Type().Key() != vdst.Type().Key() {\n\t\treturn nil, fmt.Errorf(\"incompatible map types, got %T to %T\", src, dst)\n\t}\n\n\treturn mergeMap(vdst, vsrc).Interface(), nil\n}\n\nfunc caseInsensitiveLookup(m, k reflect.Value) (reflect.Value, bool) {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/collections/merge.go#L35-L71","documentation":"Hugo's `merge` template function only supports maps. Merge iterates parameters in reverse and merges each source into the last parameter (the destination); if the destination value's reflect.Kind is not a map, merge aborts with this error, reporting the actual Go type it received.","triggerScenarios":"Calling `{{ merge $a $b }}` in a template where the last argument (the destination) is a slice, string, number, nil, or a Page rather than a map/dict. Also triggered mid-chain when an intermediate merge result isn't a map. Common calls: `merge .Params site.Params`, `merge $opts (dict ...)`.","commonSituations":"Passing `.Params.something` that is a YAML list instead of a map; front matter key defined as a list in one page and a map in another; using `merge` on `.Site.Menus` entries or slices returned by `where`; a data file (data/*.yaml) structured as an array instead of an object.","solutions":["Verify the last argument to merge is a map/dict: `{{ printf \"%T\" $dst }}` to inspect its type.","If the value can be missing, guard with `{{ with }}` or supply a default dict: `merge $src (default dict $dst)`.","Fix the front matter or data file so the key is a map (key: value pairs) rather than a list (- items).","If you meant to combine slices, use `append` or `union` instead of `merge`."],"exampleFix":"<!-- before -->\n{{ $merged := merge .Params.extra .Site.Params.tags }}  <!-- tags is a list -->\n<!-- after -->\n{{ $merged := merge .Params.extra (default dict .Site.Params.settings) }}","handlingStrategy":"type-guard","validationCode":"{{ if reflect.IsMap $dst }}{{ $merged := merge $dst $src }}{{ end }}","typeGuard":"{{/* Hugo template guard */}}{{ $isMap := reflect.IsMap $dst }}","tryCatchPattern":"{{ with try (merge $dst $src) }}{{ with .Err }}{{ warnf \"merge failed: %s\" . }}{{ else }}{{ .Value }}{{ end }}{{ end }}","preventionTips":["Verify the destination is a map (e.g. built with dict or from .Params) before calling merge","Beware of variables that may be nil or a slice when a data file is missing or malformed","Use reflect.IsMap to branch instead of assuming the shape of front matter values"],"tags":["hugo","templates","merge","type-mismatch"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}