{"id":"a88bfba4732ce6c3","repo":"gohugoio/hugo","slug":"first-argument-must-be-a-map","errorCode":null,"errorMessage":"first argument must be a map","messagePattern":"first argument must be a map","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/transform/unmarshal.go","lineNumber":51,"sourceCode":")\n\n// Unmarshal unmarshals the data given, which can be either a string, json.RawMessage\n// or a Resource. Supported formats are JSON, TOML, YAML, and CSV.\n// You can optionally provide an options map as the first argument.\nfunc (ns *Namespace) Unmarshal(args ...any) (any, error) {\n\tif len(args) < 1 || len(args) > 2 {\n\t\treturn nil, errors.New(\"unmarshal takes 1 or 2 arguments\")\n\t}\n\n\tvar data any\n\tdecoder := metadecoders.Default\n\n\tif len(args) == 1 {\n\t\tdata = args[0]\n\t} else {\n\t\tm, ok := args[0].(map[string]any)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"first argument must be a map\")\n\t\t}\n\n\t\tvar err error\n\n\t\tdata = args[1]\n\t\tdecoder, err = decodeDecoder(m)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to decode options: %w\", err)\n\t\t}\n\t}\n\n\tif r, ok := data.(resource.UnmarshableResource); ok {\n\t\tkey := r.Key()\n\n\t\tif key == \"\" {\n\t\t\treturn nil, errors.New(\"no Key set in Resource\")\n\t\t}\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/transform/unmarshal.go#L33-L69","documentation":"When `transform.Unmarshal` is called with two arguments, the first must be an options map (`map[string]any`); the second is the data. If the first argument is anything else — a string, a Resource, the data itself — this error is returned. It commonly indicates the arguments are in the wrong order.","triggerScenarios":"`{{ transform.Unmarshal $data $opts }}` (data first, options second — reversed); `{{ transform.Unmarshal \"csv\" $data }}` (passing a format name string instead of a dict); `{{ transform.Unmarshal $resource (dict ...) }}`.","commonSituations":"Assuming the options map comes after the data (many Hugo functions vary here — for Unmarshal, options come first); trying to specify the format as a plain string instead of `(dict \"format\" \"csv\")`; a `.Params` value expected to be a map but authored as a string in front matter.","solutions":["Put the options map first and the data second: `{{ transform.Unmarshal (dict \"delimiter\" \";\") $data }}`.","Wrap format/delimiter settings in a dict — a bare string like \"csv\" is not accepted.","If you don't need options, drop the first argument and call with just the data."],"exampleFix":"<!-- before -->\n{{ transform.Unmarshal $data (dict \"delimiter\" \";\") }}\n<!-- after -->\n{{ transform.Unmarshal (dict \"delimiter\" \";\") $data }}","handlingStrategy":"type-guard","validationCode":"{{ $opts := dict \"delimiter\" \";\" }}\n{{ $d := unmarshal $opts $csv }}","typeGuard":"{{/* ensure options is a map before the 2-arg form */}}\n{{ if reflect.IsMap $opts }}{{ $d = unmarshal $opts $data }}{{ else }}{{ $d = unmarshal $data }}{{ end }}","tryCatchPattern":null,"preventionTips":["In the two-argument form the FIRST argument must be the options dict, not the data","Build options with `dict`, never a string or slice","If you have no options, use the single-argument form"],"tags":["hugo","templates","unmarshal","type-error"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}