gohugoio/hugo · error
with 2 arguments, the first must be a slice of replacement…
Error message
with 2 arguments, the first must be a slice of replacement pairs, got %T
What it means
Thrown by strings.ReplacePairs in the 2-argument form when the first argument is not a slice. With exactly 2 args the contract is (sliceOfPairs, sourceString); the code checks hreflect.IsSlice and reports the actual type via %T.
Solutions
- Wrap pairs in a slice: strings.ReplacePairs (slice "a" "b" "c" "d") $s.
- Switch to the inline form for scattered pairs: strings.ReplacePairs "a" "b" $s.
- Ensure the slice elements are string-coercible.
Example fix
// before (string instead of slice):
{{ strings.ReplacePairs "a" $s }}
// after (slice of pairs):
{{ strings.ReplacePairs (slice "a" "b") $s }} Defensive patterns
Strategy: type-guard
Validate before calling
{{ if reflect.IsSlice $pairs }}{{ strings.ReplacePairs $pairs $s }}{{ else }}{{ strings.ReplacePairs "a" "b" $s }}{{ end }} Type guard
{{ if reflect.IsSlice $x }}{{ strings.ReplacePairs $x $s }}{{ else }}{{ warnf "expected slice" }}{{ end }} Prevention
- In 2-arg form the first arg must be a slice built with 'slice'.
- Switch to the inline pair form if you only have scattered pairs.
- Use reflect.IsSlice to verify dynamic values.
When it happens
Trigger: Calling {{ strings.ReplacePairs $x $s }} where $x is a string, map, or single value rather than a slice of pair strings.
Common situations: Passing a single inline pair string instead of a slice, passing a map of old->new, or confusing the 2-arg slice form with the inline pair form.
Related errors
- requires at least 2 arguments
- uneven number of replacement pairs
- arguments must be slices or arrays
- arguments to complement must be slices or arrays
- arguments to symdiff must be slices or arrays
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/0ca229cf4857dbbe.
Report an issue: GitHub.
Appendix: source
Thrown at tpl/strings/strings.go:277
// 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
}
}
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
}
}
View on GitHub (pinned to 52c9bd7908)