{"record":{"id":"116be4c7f928532d","repo":"gohugoio/hugo","slug":"uneven-number-of-replacement-pairs","errorCode":null,"errorMessage":"uneven number of replacement pairs","messagePattern":"uneven number of replacement pairs","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/strings/strings.go","lineNumber":301,"sourceCode":"\t}\n\tif p == nil {\n\t\t// inline form: ReplacePairs \"a\" \"b\" \"s\"\n\t\tp = make([]string, len(args)-1)\n\t\tfor i, v := range args[:len(args)-1] {\n\t\t\ts, err := cast.ToStringE(v)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t\tp[i] = s\n\t\t}\n\t}\n\n\tif len(p) == 0 || ss == \"\" {\n\t\treturn ss, nil\n\t}\n\n\tif len(p)%2 != 0 {\n\t\treturn \"\", fmt.Errorf(\"uneven number of replacement pairs\")\n\t}\n\n\tkey := strings.Join(p, \"\\x00\")\n\treplacer, err := ns.replacerCache.GetOrCreate(key, func() (*strings.Replacer, error) {\n\t\treturn strings.NewReplacer(p...), nil\n\t})\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn replacer.Replace(ss), nil\n}\n\n// SliceString slices a string by specifying a half-open range with\n// two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.\n// The end index can be omitted, it defaults to the string's length.\nfunc (ns *Namespace) SliceString(a any, startEnd ...any) (string, error) {\n\taStr, err := cast.ToStringE(a)","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/strings/strings.go#L283-L319","documentation":"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.","triggerScenarios":"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.","commonSituations":"Forgetting the 'new' value for the last replacement, or a slice built programmatically with an odd number of entries.","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."],"exampleFix":"// before (odd number of pairs):\n{{ strings.ReplacePairs \"a\" \"b\" \"c\" $s }}\n// after (balanced pairs):\n{{ strings.ReplacePairs \"a\" \"b\" \"c\" \"d\" $s }}","handlingStrategy":"validation","validationCode":"{{ if eq (mod (len $pairs) 2) 0 }}{{ strings.ReplacePairs $pairs $s }}{{ else }}{{ warnf \"odd pairs\" }}{{ end }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["strings","replacepairs","argument-count","pairs"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}