gohugoio/hugo · error

invalid dictionary call

Error message

invalid dictionary call

What it means

Dictionary (collections.go:160-163) pairs arguments as key,value,key,value... so the count must be even. An odd total leaves an orphan key with no value, which cannot form a map entry, so it is rejected up front.

Solutions

  1. Count arguments and ensure they pair up evenly
  2. Add the missing value for the trailing key
  3. When generating dynamically, append a placeholder value for any unpaired key

Example fix

// before
{{ dictionary "a" 1 "b" }}
// after
{{ dictionary "a" 1 "b" 2 }}
Defensive patterns

Strategy: validation

Validate before calling

{{/* build the dict from a slice of pairs to guarantee even count */}}
{{ $pairs := slice (slice "a" 1) (slice "b" 2) }}
{{ $dict := newScratch }}
{{ range $pairs }}{{ $dict.Set (index . 0) (index . 1) }}{{ end }}

Prevention

When it happens

Trigger: {{ dictionary "a" 1 "b" }} (3 args) - key "b" has no value; or any odd-length call.

Common situations: Adding a key and forgetting its value; trailing key from a generated/templated dict construction; copy-paste dropping one value.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/e615194158115f6a. Report an issue: GitHub.

Appendix: 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 52c9bd7908)