gohugoio/hugo · error
requires at least 2 arguments
Error message
requires at least 2 arguments
What it means
Hugo's `strings.ReplacePairs` is variadic: the last argument is the source string and everything before it is old/new replacement pairs (as a slice or inline). With fewer than 2 arguments there is no way to have both a source string and at least one pair specification, so Hugo rejects the call up front.
Source
Thrown at tpl/strings/strings.go:265
if len(limit) == 0 {
return strings.ReplaceAll(ss, so, sn), nil
}
lim, err := cast.ToIntE(limit[0])
if err != nil {
return "", err
}
return strings.Replace(ss, so, sn, lim), nil
}
// ReplacePairs returns a copy of a string with multiple replacements performed
// in a single pass. The last argument is the source string. Preceding arguments
// are old/new string pairs, either as a slice or as individual arguments.
func (ns *Namespace) ReplacePairs(args ...any) (string, error) {
if len(args) < 2 {
return "", fmt.Errorf("requires at least 2 arguments")
}
ss, err := cast.ToStringE(args[len(args)-1])
if err != nil {
return "", err
}
var p []string
if len(args) == 2 {
// slice form: ReplacePairs (slice "a" "b") "s"
if !hreflect.IsSlice(args[0]) {
return "", fmt.Errorf("with 2 arguments, the first must be a slice of replacement pairs, got %T", args[0])
}
p, err = cast.ToStringSliceE(args[0])
if err != nil {
return "", err
}
}View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Provide both a pairs argument and the source: slice form `{{ strings.ReplacePairs (slice "a" "b") $src }}` or inline form `{{ strings.ReplacePairs "a" "b" $src }}`.
- Remember the source string comes LAST — this differs from `replace`.
- If pairs are built dynamically, verify the slice is non-empty before calling.
Example fix
<!-- before -->
{{ strings.ReplacePairs $src }}
<!-- after -->
{{ strings.ReplacePairs (slice "old" "new") $src }} Defensive patterns
Strategy: validation
Validate before calling
{{ if ge (len $pairs) 2 }}{{ strings.Replacer $s $pairs }}{{ end }} Try / catch
if len(args) < 2 {
return "", errors.New("need at least old/new pair")
}
out, err := ns.Replacer(args...) Prevention
- Always call the replacer with at least one old/new pair
- When pairs come from site data, assert `len` before the call
- Fail the build early on empty replacement config rather than skipping silently
When it happens
Trigger: Calling `{{ strings.ReplacePairs "source" }}` with only the source string, or `{{ strings.ReplacePairs }}` with nothing — e.g. building the argument list dynamically and ending up with an empty/singleton set, or piping a lone string: `{{ "s" | strings.ReplacePairs }}`.
Common situations: Misunderstanding the signature (expecting a `replace`-like `old new src` order but supplying only the source); a `with`/`range` construct that drops the pairs variable so only the piped source remains; slice of pairs evaluating to nothing and being spread incorrectly.
Related errors
- with 2 arguments, the first must be a slice of replacement p
- uneven number of replacement pairs
- failed to convert content to string: %w
- failed to match regex pattern against string: %w
- too many arguments
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/0eeb5a114e22f537.json.
Report an issue: GitHub ↗.