{"record":{"id":"b5d856489daf7ed2","repo":"vitessio/vitess","slug":"did-not-compile","errorCode":null,"errorMessage":"did not compile?","messagePattern":"did not compile\\?","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/evalengine/expr_arithmetic.go","lineNumber":218,"sourceCode":"\t\tc.asm.Sub_ff()\n\t\tct.Type = sqltypes.Float64\n\tcase sqltypes.Decimal:\n\t\tswitch rt.Type {\n\t\tcase sqltypes.Float64:\n\t\t\tc.compileToFloat(lt, 2)\n\t\t\tc.asm.Sub_ff()\n\t\t\tct.Type = sqltypes.Float64\n\t\tdefault:\n\t\t\tc.compileToDecimal(rt, 1)\n\t\t\tc.asm.Sub_dd()\n\t\t\tct.Type = sqltypes.Decimal\n\t\t\tct.Size = max(lt.Size, rt.Size)\n\t\t\tct.Scale = max(lt.Scale, rt.Scale)\n\t\t}\n\t}\n\n\tif ct.Type == 0 {\n\t\tpanic(\"did not compile?\")\n\t}\n\n\tc.asm.jumpDestination(skip1, skip2)\n\treturn ct, nil\n}\n\nfunc (op *opArithMul) eval(left, right eval) (eval, error) {\n\treturn multiplyNumericWithError(left, right)\n}\n\nfunc (op *opArithMul) String() string { return \"*\" }\n\nfunc (op *opArithMul) compile(c *compiler, left, right IR) (ctype, error) {\n\tlt, err := left.compile(c)\n\tif err != nil {\n\t\treturn ctype{}, err\n\t}\n\tskip1 := c.compileNullCheck1(lt)","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/evalengine/expr_arithmetic.go#L200-L236","documentation":"Panic in the arithmetic expression compiler (`compile`). After merging the compile-time types of both operands, the result `ct.Type` must have been resolved to a concrete numeric type; if it is still 0, the compiler produced no type, which the code assumes is impossible — hence `panic(\"did not compile?\")`. It flags a hole in the arithmetic type-coercion table.","triggerScenarios":"Compiling an arithmetic expression (+,-,*,/) whose operand types fall through the coercion logic so that no result type is assigned (ct.Type == 0).","commonSituations":"Seen during Vitess development when new sqltypes are added to the arithmetic matrix without a covering rule, or when a refactor drops a coercion branch. Rare on released versions; would surface as a vtgate crash on a specific query.","solutions":["Identify the operand type combination from the query and add the missing coercion rule in expr_arithmetic.go","Return a clear vterrors error instead of panicking so the query fails gracefully","Add a regression test for the type combination","Upgrade to a Vitess release with the fix"],"exampleFix":"// before\nif ct.Type == 0 {\n    panic(\"did not compile?\")\n}\n// after\nif ct.Type == 0 {\n    return ctype{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"arithmetic compile produced no type\")","handlingStrategy":"type-guard","validationCode":"if ct.Type == 0 {\n    return ctype{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"arithmetic type unresolved for operands %v/%v\", lt.Type, rt.Type)\n}","typeGuard":"func isResolvedNumeric(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, \"arithmetic compile panic: %v\", r)\n    }\n}()","preventionTips":["Extend the arithmetic coercion table whenever new numeric sqltypes are added","Test compile() with all operand-type combinations","Return typed errors instead of panics at compiler boundaries"],"tags":["go","panic","compiler","type-system","arithmetic"],"backgroundTag":"unreachable-invariant-panic","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}