{"id":"8afb5842e2524926","repo":"gohugoio/hugo","slug":"must-provide-a-resource-and-optionally-an-options","errorCode":null,"errorMessage":"must provide a Resource and optionally an options map","messagePattern":"must provide a Resource and optionally an options map","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/openapi/openapi3/openapi3.go","lineNumber":73,"sourceCode":"// OpenAPIDocument represents an OpenAPI 3 document.\ntype OpenAPIDocument struct {\n\t*kopenapi3.T\n\tidentityGroup identity.Identity\n}\n\nfunc (o *OpenAPIDocument) GetIdentityGroup() identity.Identity {\n\treturn o.identityGroup\n}\n\ntype unmarshalOptions struct {\n\t// Options passed to resources.GetRemote when resolving remote $ref.\n\tGetRemote map[string]any\n}\n\n// Unmarshal unmarshals the given resource into an OpenAPI 3 document.\nfunc (ns *Namespace) Unmarshal(ctx context.Context, args ...any) (*OpenAPIDocument, error) {\n\tif len(args) < 1 || len(args) > 2 {\n\t\treturn nil, errors.New(\"must provide a Resource and optionally an options map\")\n\t}\n\n\tr := args[0].(resource.UnmarshableResource)\n\tkey := r.Key()\n\tif key == \"\" {\n\t\treturn nil, errors.New(\"no Key set in Resource\")\n\t}\n\n\tvar opts unmarshalOptions\n\tif len(args) > 1 {\n\t\toptsm, err := hmaps.ToStringMapE(args[1])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := mapstructure.WeakDecode(optsm, &opts); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tkey += \"_\" + hashing.HashString(optsm)","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/openapi/openapi3/openapi3.go#L55-L91","documentation":"`openapi3.Unmarshal` (tpl/openapi/openapi3/openapi3.go:73) accepts exactly one or two arguments: a Resource (something implementing UnmarshableResource, typically from `resources.Get`) and an optional options map (currently just `GetRemote` options for resolving remote $refs). Zero arguments or more than two fail this arity check before any parsing happens.","triggerScenarios":"`{{ openapi3.Unmarshal }}` with no arguments, or with three or more, e.g. passing the spec path as a string alongside other values instead of a single Resource plus an options dict.","commonSituations":"Calling the function with a file path string plus extra args instead of `resources.Get`-ing the spec first; templates written against the pre-0.121 `getJSON`-style APIs; passing options as separate key/value arguments rather than one `dict`.","solutions":["Fetch the spec as a Resource first and pass it: `{{ $api := resources.Get \"api/openapi.yaml\" | openapi3.Unmarshal }}`.","If passing options, bundle them into a single map: `{{ $api := openapi3.Unmarshal $r (dict \"getRemote\" (dict \"headers\" ...)) }}`.","Remove any extra positional arguments beyond the Resource and one options map."],"exampleFix":"<!-- before -->\n{{ $api := openapi3.Unmarshal \"api/openapi.yaml\" true }}\n<!-- after -->\n{{ $r := resources.Get \"api/openapi.yaml\" }}\n{{ $api := openapi3.Unmarshal $r }}","handlingStrategy":"type-guard","validationCode":"{{ $spec := resources.Get \"api/openapi.yaml\" }}\n{{ if $spec }}\n  {{ $doc := openapi3.Unmarshal $spec }}\n{{ end }}","typeGuard":"{{/* first arg must be a Resource, optional second a map */}}\n{{ $isResource := ne $spec nil }}\n{{ $optsOK := or (not $opts) (reflect.IsMap $opts) }}","tryCatchPattern":null,"preventionTips":["Pass the Resource from resources.Get/resources.GetRemote directly, not a string path or file content","If passing options, make it a dict as the second argument","Check the resource is non-nil before calling openapi3.Unmarshal","Don't pipe the spec through transforms that return strings before Unmarshal"],"tags":["hugo","templates","openapi","arguments"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}