gohugoio/hugo · error

must provide a Resource and optionally an options map

Error message

must provide a Resource and optionally an options map

What it means

`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.

Source

Thrown at tpl/openapi/openapi3/openapi3.go:73

// OpenAPIDocument represents an OpenAPI 3 document.
type OpenAPIDocument struct {
	*kopenapi3.T
	identityGroup identity.Identity
}

func (o *OpenAPIDocument) GetIdentityGroup() identity.Identity {
	return o.identityGroup
}

type unmarshalOptions struct {
	// Options passed to resources.GetRemote when resolving remote $ref.
	GetRemote map[string]any
}

// Unmarshal unmarshals the given resource into an OpenAPI 3 document.
func (ns *Namespace) Unmarshal(ctx context.Context, args ...any) (*OpenAPIDocument, error) {
	if len(args) < 1 || len(args) > 2 {
		return nil, errors.New("must provide a Resource and optionally an options map")
	}

	r := args[0].(resource.UnmarshableResource)
	key := r.Key()
	if key == "" {
		return nil, errors.New("no Key set in Resource")
	}

	var opts unmarshalOptions
	if len(args) > 1 {
		optsm, err := hmaps.ToStringMapE(args[1])
		if err != nil {
			return nil, err
		}
		if err := mapstructure.WeakDecode(optsm, &opts); err != nil {
			return nil, err
		}
		key += "_" + hashing.HashString(optsm)

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Fetch the spec as a Resource first and pass it: `{{ $api := resources.Get "api/openapi.yaml" | openapi3.Unmarshal }}`.
  2. If passing options, bundle them into a single map: `{{ $api := openapi3.Unmarshal $r (dict "getRemote" (dict "headers" ...)) }}`.
  3. Remove any extra positional arguments beyond the Resource and one options map.

Example fix

<!-- before -->
{{ $api := openapi3.Unmarshal "api/openapi.yaml" true }}
<!-- after -->
{{ $r := resources.Get "api/openapi.yaml" }}
{{ $api := openapi3.Unmarshal $r }}
Defensive patterns

Strategy: type-guard

Validate before calling

{{ $spec := resources.Get "api/openapi.yaml" }}
{{ if $spec }}
  {{ $doc := openapi3.Unmarshal $spec }}
{{ end }}

Type guard

{{/* first arg must be a Resource, optional second a map */}}
{{ $isResource := ne $spec nil }}
{{ $optsOK := or (not $opts) (reflect.IsMap $opts) }}

Prevention

When it happens

Trigger: `{{ 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.

Common situations: 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`.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/8afb5842e2524926.json. Report an issue: GitHub ↗.