gohugoio/hugo · error
invalid dictionary call
Error message
invalid dictionary call
What it means
The `dict` template function builds a map from alternating key/value arguments, so it requires an even argument count. An odd number of values means some key has no value (or vice versa), and Hugo rejects the whole call rather than guessing.
Source
Thrown at tpl/collections/collections.go:162
str.WriteString(valStr)
default:
str.WriteString(valStr + d)
}
}
default:
return "", fmt.Errorf("can't iterate over %T", l)
}
return str.String(), nil
}
// Dictionary creates a new map from the given parameters by
// treating values as key-value pairs. The number of values must be even.
// The keys can be string slices, which will create the needed nested structure.
func (ns *Namespace) Dictionary(values ...any) (map[string]any, error) {
if len(values)%2 != 0 {
return nil, errors.New("invalid dictionary call")
}
root := make(map[string]any)
for i := 0; i < len(values); i += 2 {
dict := root
var key string
switch v := values[i].(type) {
case string:
key = v
case []string:
for i := range len(v) - 1 {
key = v[i]
var m map[string]any
v, found := dict[key]
if found {
m = v.(map[string]any)
} else {View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Count the arguments — every key needs exactly one value: `{{ dict "a" 1 "b" 2 }}`.
- Parenthesize compound value expressions so they count as one argument: `{{ dict "title" (printf "%s — %s" .Title .Site.Title) }}`.
- When passing dicts to partials, build them stepwise with `merge` instead of one long argument list to keep pairs balanced.
Example fix
<!-- before -->
{{ partial "card.html" (dict "page" . "class" ) }}
<!-- after -->
{{ partial "card.html" (dict "page" . "class" "featured") }} Defensive patterns
Strategy: validation
Validate before calling
{{/* dict requires an even number of args: key value key value */}}
{{ $d := dict "name" "hugo" "version" site.Hugo.Version }} Prevention
- Ensure dict receives an even number of arguments — every key needs a value
- When a value is conditional, supply an explicit default (`| default ""`) rather than omitting the pair
- When building dicts dynamically with merge, verify each fragment is itself a valid dict
When it happens
Trigger: `{{ dict "a" 1 "b" }}` — any `dict` call with an odd number of arguments, often caused by a value expression that got split or a trailing key left behind while editing.
Common situations: Forgetting to parenthesize a compound value (`dict "page" .Title .Section` passes 3 args), deleting a value but leaving its key during refactoring, or building partials' context dicts with conditionally-appended arguments that unbalance the pairs.
Related errors
- need at least 2 arguments to append
- invalid dictionary key
- symdiff: failed to convert value: %w
- arguments to symdiff must be slices or arrays
- errWrongArgStructure
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/e615194158115f6a.json.
Report an issue: GitHub ↗.