{"record":{"id":"76ce046e4bc52fe6","repo":"vitessio/vitess","slug":"unsupported-type-t","errorCode":null,"errorMessage":"unsupported type %T","messagePattern":"unsupported type %T","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/evalengine/eval_numeric.go","lineNumber":229,"sourceCode":"\t\t\t}\n\t\t\treturn &evalFloat{f: 0.0}, true\n\t\tcase json.TypeNumber:\n\t\t\tf, ok := e.Float64()\n\t\t\treturn &evalFloat{f: f}, ok\n\t\tcase json.TypeString:\n\t\t\tval, err := fastparse.ParseFloat64(e.Raw())\n\t\t\treturn &evalFloat{f: val}, err == nil\n\t\tdefault:\n\t\t\treturn &evalFloat{f: 0}, true\n\t\t}\n\tcase *evalTemporal:\n\t\treturn &evalFloat{f: e.toFloat()}, true\n\tcase *evalEnum:\n\t\treturn &evalFloat{f: float64(enumNumeric(e.value))}, e.value != -1\n\tcase *evalSet:\n\t\treturn &evalFloat{f: float64(e.set)}, true\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unsupported type %T\", e))\n\t}\n}\n\nfunc evalToDecimal(e eval, m, d int32) *evalDecimal {\n\tswitch e := e.(type) {\n\tcase evalNumeric:\n\t\treturn e.toDecimal(m, d)\n\tcase *evalBytes:\n\t\tif e.isHexLiteral() {\n\t\t\thex, ok := e.toNumericHex()\n\t\t\tif !ok {\n\t\t\t\t// overflow\n\t\t\t\treturn newEvalDecimal(decimal.Zero, m, d)\n\t\t\t}\n\t\t\treturn hex.toDecimal(m, d)\n\t\t}\n\t\tif e.isBitLiteral() {\n\t\t\tbit, ok := e.toNumericBit()","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/evalengine/eval_numeric.go#L211-L247","documentation":"evalToFloat converts any eval engine value to a float. When handed a value whose concrete type is not one of the handled numeric/enum/set/string-ish types, it panics with \"unsupported type %T\". This indicates the eval engine received an AST/expr value type that numeric coercion was never designed to handle, i.e. an internal invariant violation rather than user data error.","triggerScenarios":"Calling evalToFloat (directly or via evalCoerce, valueToEvalCast, evalCompare, compareAllFloat) with an eval implementation not covered by the type switch, e.g. a newly added eval type (like a new temporal or JSON variant) that was not added to the switch in eval_numeric.go.","commonSituations":"Developers extending the eval engine with a new eval type but forgetting to update evalToFloat; plugin or comparison code feeding an unexpected expression result into float comparison.","solutions":["Identify the type printed in the panic (%T) and add a case for it in evalToFloat in go/vt/vtgate/evalengine/eval_numeric.go","If the type should never reach float coercion, fix the caller (evalCoerce/evalCompare) to route or reject that type earlier","Check the vitess version; upgrade to a release where the new type is supported in numeric coercion"],"exampleFix":"// before\ndefault:\n    panic(fmt.Sprintf(\"unsupported type %T\", e))\n// after\ncase *evalMyNewType:\n    return &evalFloat{f: e.toFloat()}, true\ndefault:\n    panic(fmt.Sprintf(\"unsupported type %T\", e))","handlingStrategy":"type-guard","validationCode":"// before relying on float coercion\nif _, ok := v.(evalNumeric); !ok {\n    switch v.(type) {\n    case *evalEnum, *evalSet:\n    default:\n        return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, \"cannot coerce %T to float\", v)\n    }\n}","typeGuard":"func isFloatCoercible(e eval) bool {\n    switch e.(type) {\n    case evalNumeric, *evalEnum, *evalSet:\n        return true\n    default:\n        return false\n    }\n}","tryCatchPattern":"// Go panics are not errors; recover at query-evaluation boundary\nfunc safeEvalToFloat(e eval) (f *evalFloat, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"evalToFloat: %v\", r)\n        }\n    }()\n    fl, _ := evalToFloat(e)\n    return fl, nil\n}","preventionTips":["When adding a new eval type, grep for 'unsupported type' in eval_numeric.go and update all conversion switches","Run the evalengine unit tests that exercise compare/coerce for every type","Route non-scalar types away from numeric coercion during expression type analysis"],"tags":["go","panic","evalengine","type-coercion"],"backgroundTag":"unsupported-type-coercion","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}