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

  1. Wrap pairs in a slice: strings.ReplacePairs (slice "a" "b" "c" "d") $s.
  2. Switch to the inline form for scattered pairs: strings.ReplacePairs "a" "b" $s.
  3. 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

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


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)