gohugoio/hugo · error
uneven number of replacement pairs
Error message
uneven number of replacement pairs
What it means
Thrown by strings.ReplacePairs after collecting all pair elements when len(p) is odd. strings.NewReplacer requires old/new pairs, so an odd count means one element has no partner.
Solutions
- Ensure replacement pairs are balanced: every old value has a following new value.
- In slice form, check len(slice) is even before passing.
- Add the missing partner value for the trailing entry.
Example fix
// before (odd number of pairs):
{{ strings.ReplacePairs "a" "b" "c" $s }}
// after (balanced pairs):
{{ strings.ReplacePairs "a" "b" "c" "d" $s }} Defensive patterns
Strategy: validation
Validate before calling
{{ if eq (mod (len $pairs) 2) 0 }}{{ strings.ReplacePairs $pairs $s }}{{ else }}{{ warnf "odd pairs" }}{{ end }} Prevention
- Ensure every old value has a matching new value.
- For dynamic slices, check len is even before passing.
- Add the missing partner when you see this error.
When it happens
Trigger: Inline form with an odd number of pair args (e.g. strings.ReplacePairs "a" "b" "c" $s) or a slice form whose length is odd (e.g. (slice "a" "b" "c")). The check runs after argument normalization, before constructing the Replacer.
Common situations: Forgetting the 'new' value for the last replacement, or a slice built programmatically with an odd number of entries.
Related errors
- requires at least 2 arguments
- with 2 arguments, the first must be a slice of replacement…
- Defer does not take any arguments
- ellipsis must be a string
- end argument must be integer
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/116be4c7f928532d.
Report an issue: GitHub.
Appendix: source
Thrown at tpl/strings/strings.go:301
}
if p == nil {
// inline form: ReplacePairs "a" "b" "s"
p = make([]string, len(args)-1)
for i, v := range args[:len(args)-1] {
s, err := cast.ToStringE(v)
if err != nil {
return "", err
}
p[i] = s
}
}
if len(p) == 0 || ss == "" {
return ss, nil
}
if len(p)%2 != 0 {
return "", fmt.Errorf("uneven number of replacement pairs")
}
key := strings.Join(p, "\x00")
replacer, err := ns.replacerCache.GetOrCreate(key, func() (*strings.Replacer, error) {
return strings.NewReplacer(p...), nil
})
if err != nil {
return "", err
}
return replacer.Replace(ss), nil
}
// SliceString slices a string by specifying a half-open range with
// two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.
// The end index can be omitted, it defaults to the string's length.
func (ns *Namespace) SliceString(a any, startEnd ...any) (string, error) {
aStr, err := cast.ToStringE(a)View on GitHub (pinned to 52c9bd7908)