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
- Obtain the spec via the standard resource functions: `{{ $r := resources.Get "api/openapi.yaml" }}` and pass `$r`.
- Verify the resource exists and is non-nil before calling Unmarshal: `{{ with resources.Get "api/openapi.yaml" }}{{ $api := openapi3.Unmarshal . }}{{ end }}`.
- 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
- Use resources obtained from Hugo's resource pipeline (resources.Get, GetRemote, page resources) — these carry a Key
- Avoid hand-constructed or wrapped objects that mimic a Resource without a Key
- If a transform chain drops identity, unmarshal the original resource instead of the derived one
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
- must provide a Resource and optionally an options map
- MIME %q not supported
- resources.PostProcess cannot be used in a deferred template
- no Resource provided in transformation
- type %T not supported in Resource transformations
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/20db514a388138ba.json.
Report an issue: GitHub ↗.