gohugoio/hugo · error
no Key set in Resource
Error message
no Key set in Resource
What it means
Thrown by transform.Unmarshal when the data argument is a Resource (implements UnmarshableResource) but its Key() returns an empty string (tpl/transform/unmarshal.go:64-67). The Key is used for caching the unmarshalled result; an empty key would defeat caching and is treated as a misconfiguration.
Source
Thrown at tpl/transform/unmarshal.go:67
m, ok := args[0].(map[string]any)
if !ok {
return nil, errors.New("first argument must be a map")
}
var err error
data = args[1]
decoder, err = decodeDecoder(m)
if err != nil {
return nil, fmt.Errorf("failed to decode options: %w", err)
}
}
if r, ok := data.(resource.UnmarshableResource); ok {
key := r.Key()
if key == "" {
return nil, errors.New("no Key set in Resource")
}
if decoder != metadecoders.Default {
key += decoder.OptionsKey()
}
v, err := ns.cacheUnmarshal.GetOrCreate(key, func(string) (*resources.StaleValue[any], error) {
var f metadecoders.Format
if decoder.Format != "" {
f = metadecoders.FormatFromString(decoder.Format)
if f == "" {
return nil, fmt.Errorf("format %q not supported", decoder.Format)
}
} else {
f = metadecoders.FormatFromStrings(r.MediaType().Suffixes()...)
if f == "" {
return nil, fmt.Errorf("MIME %q not supported", r.MediaType())
}View on GitHub (pinned to 52c9bd7908)
Solutions
- Ensure the resource has a Key by giving it a path: use resources.GetRemote with a key, or name the resource so a key is derived.
- If the resource is built via resources.FromString, materialize it through a pipeline step that assigns a key.
- Alternatively, read the resource content into a string and Unmarshal the string instead of the Resource.
Example fix
// before
{{ $r := resources.FromString "tmp" .Raw }}
{{ transform.Unmarshal $r }}
// after
{{ transform.Unmarshal $r.Content }} Defensive patterns
Strategy: validation
Validate before calling
{{/* Prefer Unmarshalling a string, or ensure the Resource has a Key */}}
{{ transform.Unmarshal $r.Content }} Prevention
- Avoid passing resources created without a key (e.g. resources.FromString) directly to Unmarshal.
- Give remote/string resources a name so a Key is derived.
- Unmarshal the resource's content string instead when a key cannot be set.
When it happens
Trigger: Calling {{ transform.Unmarshal .Resource }} (or with options) where .Resource is a dynamically created resource (e.g. from resources.FromString) that has no Key/Permalink set.
Common situations: Using resources.FromString or resources.Concat without assigning a name/key; passing a remote resource fetched without a key; resources created in templates that bypass the resource system's key assignment.
Related errors
- unmarshal takes 1 or 2 arguments
- first argument must be a map
- unknown format
- must provide an URL and optionally an options map
- must provide one or more Resource objects to concat
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/f9992b46af268bfd.
Report an issue: GitHub.