gohugoio/hugo · error

no Key set in Resource

Error message

no Key set in Resource

What it means

After the arity check, `openapi3.Unmarshal` (tpl/openapi/openapi3/openapi3.go:79) calls `Key()` on the passed Resource to build its cache key. A Resource with an empty Key cannot be cached or identified, so Hugo rejects it. This typically means the value passed is not a normal file-backed asset resource.

Source

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

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)
	}

	v, err := ns.cache.GetOrCreate(key, func(string) (*OpenAPIDocument, error) {
		f := metadecoders.FormatFromStrings(r.MediaType().Suffixes()...)
		if f == "" {
			return nil, fmt.Errorf("MIME %q not supported", r.MediaType())

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Obtain the spec via the standard resource functions: `{{ $r := resources.Get "api/openapi.yaml" }}` and pass `$r`.
  2. Verify the resource exists and is non-nil before calling Unmarshal: `{{ with resources.Get "api/openapi.yaml" }}{{ $api := openapi3.Unmarshal . }}{{ end }}`.
  3. Upgrade Hugo if a known resource type is missing its Key in your version.

Example fix

<!-- before: passing an ad-hoc value -->
{{ $api := openapi3.Unmarshal $someObject }}
<!-- after -->
{{ with resources.Get "api/openapi.yaml" }}
  {{ $api := openapi3.Unmarshal . }}
{{ end }}
Defensive patterns

Strategy: validation

Validate before calling

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

Prevention

When it happens

Trigger: Passing a Resource whose `Key()` returns "" — e.g. a hand-constructed or exotic resource type rather than one obtained from `resources.Get`, `resources.GetRemote`, or `resources.FromString`.

Common situations: Passing the result of a failed/odd resource pipeline, custom modules producing resources without keys, or (in older Hugo versions) certain remote/derived resources that lacked keys. Rare in practice; usually indicates the wrong object is being passed.

Related errors


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