{"record":{"id":"653da946e128b4dc","repo":"gohugoio/hugo","slug":"incompatible-types-for-comparison-v-and-v","errorCode":null,"errorMessage":"incompatible types for comparison: %v and %v","messagePattern":"incompatible types for comparison: (.+?) and (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/internal/go_templates/texttemplate/funcs.go","lineNumber":480,"sourceCode":"\targ1 = indirectInterface(arg1)\n\tif len(arg2) == 0 {\n\t\treturn false, errNoComparison\n\t}\n\tk1, _ := basicKind(arg1)\n\tfor _, arg := range arg2 {\n\t\targ = indirectInterface(arg)\n\t\tk2, _ := basicKind(arg)\n\t\ttruth := false\n\t\tif k1 != k2 {\n\t\t\t// Special case: Can compare integer values regardless of type's sign.\n\t\t\tswitch {\n\t\t\tcase k1 == intKind && k2 == uintKind:\n\t\t\t\ttruth = arg1.Int() >= 0 && uint64(arg1.Int()) == arg.Uint()\n\t\t\tcase k1 == uintKind && k2 == intKind:\n\t\t\t\ttruth = arg.Int() >= 0 && arg1.Uint() == uint64(arg.Int())\n\t\t\tdefault:\n\t\t\t\tif arg1.IsValid() && arg.IsValid() {\n\t\t\t\t\treturn false, fmt.Errorf(\"incompatible types for comparison: %v and %v\", arg1.Type(), arg.Type())\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tswitch k1 {\n\t\t\tcase boolKind:\n\t\t\t\ttruth = arg1.Bool() == arg.Bool()\n\t\t\tcase complexKind:\n\t\t\t\ttruth = arg1.Complex() == arg.Complex()\n\t\t\tcase floatKind:\n\t\t\t\ttruth = arg1.Float() == arg.Float()\n\t\t\tcase intKind:\n\t\t\t\ttruth = arg1.Int() == arg.Int()\n\t\t\tcase stringKind:\n\t\t\t\ttruth = arg1.String() == arg.String()\n\t\t\tcase uintKind:\n\t\t\t\ttruth = arg1.Uint() == arg.Uint()\n\t\t\tdefault:\n\t\t\t\tif !canCompare(arg1, arg) {","sourceCodeStart":462,"sourceCodeEnd":498,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/internal/go_templates/texttemplate/funcs.go#L462-L498","documentation":"Raised by the `eq` template function when both operands are valid (non-nil) but their basic kinds differ and are not the int/uint cross-sign special case (funcs.go:478-481). `eq` only compares like kinds (after the integer cross-sign allowance); mismatches like string-vs-int or bool-vs-string are rejected. Format: `type1 type2`.","triggerScenarios":"`{{eq .Count \"5\"}}` (int vs string); `{{eq .Flag 1}}` (bool vs int); `{{eq .Name 3}}` (string vs int); comparing a number from JSON to a string literal in template.","commonSituations":"Front matter values loaded as strings (YAML/csv) compared to numeric literals; JSON numbers vs template string literals; loose typing crossing module boundaries.","solutions":["Coerce both sides to the same type before comparing: `{{eq (int .Count) 5}}` or `{{eq (printf \"%v\" .Count) \"5\"}}`.","Make the data layer produce consistently typed values.","Use the appropriate builtin (`float`, `int`, `string`) to normalize."],"exampleFix":"// before\n{{eq .Qty \"5\"}}   // .Qty is int\n\n// after\n{{eq (printf \"%d\" .Qty) \"5\"}}","handlingStrategy":"type-guard","validationCode":"// Normalize both operands to the same kind before eq:\n//   {{eq (int .Qty) 5}}\n//   {{eq (printf \"%d\" .Qty) \"5\"}}","typeGuard":"func sameBasicKind(a, b interface{}) bool {\n    ka, _ := basicKindOf(a)\n    kb, _ := basicKindOf(b)\n    return ka == kb || (ka == \"int\" && kb == \"uint\") || (ka == \"uint\" && kb == \"int\")\n}\n// where basicKindOf maps via reflect as in funcs.go:418","tryCatchPattern":null,"preventionTips":["Normalize front-matter values to typed fields at the data boundary.","Use int/float/string builtins to coerce before comparing.","Document expected operand types in template comments."],"tags":["template","comparison","eq","type-mismatch","text-template"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}