{"record":{"id":"ca3088be31b124fe","repo":"gohugoio/hugo","slug":"can-t-apply-the-operator-to-the-values","errorCode":null,"errorMessage":"can't apply the operator to the values","messagePattern":"can't apply the operator to the values","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/math/math.go","lineNumber":51,"sourceCode":"\t\tswitch bv.Kind() {\n\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\t\tisInt = true\n\t\t\tbi = bv.Int()\n\t\tcase reflect.Float32, reflect.Float64:\n\t\t\tisFloat = true\n\t\t\taf = float64(ai) // may overflow\n\t\t\tbf = bv.Float()\n\t\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\t\tbu = bv.Uint()\n\t\t\tif ai >= 0 {\n\t\t\t\tisUint = true\n\t\t\t\tau = uint64(ai)\n\t\t\t} else {\n\t\t\t\tisInt = true\n\t\t\t\tbi = int64(bu) // may overflow\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil, errors.New(\"can't apply the operator to the values\")\n\t\t}\n\tcase reflect.Float32, reflect.Float64:\n\t\tisFloat = true\n\t\taf = av.Float()\n\t\tswitch bv.Kind() {\n\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\t\tbf = float64(bv.Int()) // may overflow\n\t\tcase reflect.Float32, reflect.Float64:\n\t\t\tbf = bv.Float()\n\t\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\t\tbf = float64(bv.Uint()) // may overflow\n\t\tdefault:\n\t\t\treturn nil, errors.New(\"can't apply the operator to the values\")\n\t\t}\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\tau = av.Uint()\n\t\tswitch bv.Kind() {\n\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/common/math/math.go#L33-L69","documentation":"DoArithmetic uses reflection on both operands; this throw (math.go:51) is the default branch when the first operand is an int kind but the second operand's reflect.Kind is not int/float/uint (e.g. string, bool, nil, struct), so the operator (+,-,*,/) cannot be applied.","triggerScenarios":"Calling a Hugo math template function (add/sub/mul/div) with an int first operand and a non-numeric second operand, e.g. `{{ add 1 \"x\" }}` or `{{ add .Qty nil }}`.","commonSituations":"Template receives a string from front matter where a number was expected; a nil/missing value reaching arithmetic; a bool passed accidentally.","solutions":["Ensure both operands are numeric (int/uint/float) before calling math functions","Coerce front matter values to numbers with int/float in templates","Add a default/fallback so the operand is never nil or a string"],"exampleFix":"{{/* before */}}\n{{ add .Params.qty \"5\" }}\n{{/* after */}}\n{{ add .Params.qty (int \"5\") }}","handlingStrategy":"type-guard","validationCode":"func isNumeric(v any) bool {\n    switch reflect.ValueOf(v).Kind() {\n    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,\n        reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,\n        reflect.Float32, reflect.Float64:\n        return true\n    }\n    return false\n}\nif !isNumeric(b) { /* coerce, default, or skip */ }","typeGuard":"func isNumeric(v any) bool { /* body as in validationCode */ }","tryCatchPattern":"if r, err := math.DoArithmetic(a, b, op); err != nil {\n    // coerce operands or substitute a numeric default\n} else { use(r) }","preventionTips":["Validate template params are numeric before arithmetic","Use Hugo's int/float cast functions on string front matter values"],"tags":["math","templates","reflection","go","hugo"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}