{"record":{"id":"5d4e124a766a0d73","repo":"vitessio/vitess","slug":"unexpected-numeric-type","errorCode":null,"errorMessage":"unexpected Numeric type","messagePattern":"unexpected Numeric type","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/evalengine/expr_arithmetic.go","lineNumber":538,"sourceCode":"\t\t\tneg = sqltypes.Int64\n\t\t\tc.asm.Neg_i()\n\t\t}\n\tcase sqltypes.Uint64:\n\t\tif arg.Flag&flagHex != 0 {\n\t\t\tneg = sqltypes.Float64\n\t\t\tc.asm.Neg_hex()\n\t\t} else {\n\t\t\tneg = sqltypes.Int64\n\t\t\tc.asm.Neg_u()\n\t\t}\n\tcase sqltypes.Float64:\n\t\tneg = sqltypes.Float64\n\t\tc.asm.Neg_f()\n\tcase sqltypes.Decimal:\n\t\tneg = sqltypes.Decimal\n\t\tc.asm.Neg_d()\n\tdefault:\n\t\tpanic(\"unexpected Numeric type\")\n\t}\n\n\tc.asm.jumpDestination(skip)\n\treturn ctype{\n\t\tType:  neg,\n\t\tFlag:  nullableFlags(arg.Flag),\n\t\tSize:  arg.Size,\n\t\tScale: arg.Scale,\n\t\tCol:   collationNumeric,\n\t}, nil\n}\n\nfunc nullableFlags(flag typeFlag) typeFlag {\n\treturn flag & (flagNull | flagNullable)\n}\n","sourceCodeStart":520,"sourceCodeEnd":554,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/evalengine/expr_arithmetic.go#L520-L554","documentation":"Panic in the unary-minus compiler path of `compile`. The switch converts the argument's compile-time type into the negation result type: Int->Int/Uint->Float64/Decimal->Decimal, each emitting a matching ASM op. A numeric type outside that set (or an unset type) reaches `panic(\"unexpected Numeric type\")`, meaning the type-coercion stage upstream let a non-negatable type through.","triggerScenarios":"Compiling `-expr` where the argument's resolved type is not one of the numeric types the switch expects (e.g. a newly added numeric type, or a type left at 0).","commonSituations":"Development-time issue after introducing new numeric sqltypes or changing coercion rules; on a released binary it would manifest as a vtgate panic for a specific unary-minus query.","solutions":["Determine the argument type from the failing query and add the corresponding case (and ASM op) to the switch","Tighten upstream coercion so only Int/Uint/Float64/Decimal reach this path","Replace the panic with a wrapped internal error for graceful query failure","Upgrade to a release that handles the type"],"exampleFix":"// before\ndefault:\n    panic(\"unexpected Numeric type\")\n// after\ndefault:\n    return ctype{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"cannot negate type %v\", arg.Type)","handlingStrategy":"type-guard","validationCode":"switch arg.Type {\ncase sqltypes.Int64, sqltypes.Uint64, sqltypes.Float64, sqltypes.Decimal:\n    // ok\ndefault:\n    return ctype{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"unary minus on unsupported type %v\", arg.Type)\n}","typeGuard":"func isNegatableNumeric(t sqltypes.Type) bool {\n    switch t {\n    case sqltypes.Int8, sqltypes.Int16, sqltypes.Int24, sqltypes.Int32, sqltypes.Int64,\n        sqltypes.Uint8, sqltypes.Uint16, sqltypes.Uint24, sqltypes.Uint32, sqltypes.Uint64,\n        sqltypes.Float32, sqltypes.Float64, sqltypes.Decimal:\n        return true\n    }\n    return false\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        err = vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"negation compile panic: %v\", r)\n    }\n}()","preventionTips":["Ensure upstream coercion normalizes all numeric types to the four switch cases","Add compile tests for unary minus on every numeric type","Fail with vterrors instead of panicking on unsupported types"],"tags":["go","panic","compiler","arithmetic","type-system"],"backgroundTag":"unreachable-invariant-panic","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}