{"record":{"id":"98d9fd78011438e6","repo":"vitessio/vitess","slug":"vt13001-98d9fd","errorCode":"VT13001","errorMessage":"VT13001: [BUG] unhandled default case","messagePattern":"VT13001: \\[BUG\\] unhandled default case","errorType":"error_code","errorClass":"VitessError","httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/planbuilder/operators/phases.go","lineNumber":68,"sourceCode":"\t\treturn \"physicalTransform\"\n\tcase initialPlanning:\n\t\treturn \"initial horizon planning optimization\"\n\tcase pullDistinctFromUnion:\n\t\treturn \"pull distinct from UNION\"\n\tcase delegateAggregation:\n\t\treturn \"split aggregation between vtgate and mysql\"\n\tcase recursiveCTEHorizons:\n\t\treturn \"expand recursive CTE horizons\"\n\tcase addAggrOrdering:\n\t\treturn \"optimize aggregations with ORDER BY\"\n\tcase cleanOutPerfDistinct:\n\t\treturn \"optimize Distinct operations\"\n\tcase subquerySettling:\n\t\treturn \"settle subqueries\"\n\tcase dmlWithInput:\n\t\treturn \"expand update/delete to dml with input\"\n\tdefault:\n\t\tpanic(vterrors.VT13001(\"unhandled default case\"))\n\t}\n}\n\nfunc (p Phase) shouldRun(s semantics.QuerySignature) bool {\n\tswitch p {\n\tcase pullDistinctFromUnion:\n\t\treturn s.Union\n\tcase delegateAggregation:\n\t\treturn s.Aggregation\n\tcase recursiveCTEHorizons:\n\t\treturn s.RecursiveCTE\n\tcase addAggrOrdering:\n\t\treturn s.Aggregation\n\tcase cleanOutPerfDistinct:\n\t\treturn s.Distinct\n\tcase subquerySettling:\n\t\treturn s.SubQueries\n\tcase dmlWithInput:","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/planbuilder/operators/phases.go#L50-L86","documentation":"VT13001 internal-bug panic in Phase.String(). The method enumerates all known planning phases; a Phase value outside the enumerated cases (uninitialized or future/foreign value) hits the default and panics. It exists purely to catch programming errors when a new phase is added without updating String.","triggerScenarios":"Calling String() (e.g. via logging/tracing a phase) on a Phase value not covered by the switch — typically a newly added phase constant whose String case was forgotten, or a zero-value/uninitialized Phase.","commonSituations":"Development of Vitess itself (adding a phase to phases.go without updating String); end users only see it via a planner bug's stack trace in logs.","solutions":["Add the missing Phase case to the String() switch in go/vt/vtgate/planbuilder/operators/phases.go","File a bug with the stack trace if this appears without local code changes","Run on the latest release where all phases are covered"],"exampleFix":"// before\ncase dmlWithInput:\n    return \"expand update/delete to dml with input\"\ndefault:\n    panic(vterrors.VT13001(\"unhandled default case\"))\n// after: add the new phase before default\ncase myNewPhase:\n    return \"my new phase\"\ndefault:\n    panic(vterrors.VT13001(\"unhandled default case\"))","handlingStrategy":"type-guard","validationCode":"// Vitess contributors: ensure every Phase constant has a String case\nfor (const p of allPhases) {\n  if (phaseToString(p) === undefined) throw new Error('missing String case for phase ' + p);\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["When adding a Phase constant, update String() and shouldRun() in the same change","Enable exhaustive-switch linters","Only maintainers/developers normally encounter this"],"tags":["vtgate","planbuilder","internal-bug","exhaustiveness"],"backgroundTag":"internal-bug-panic-vt13001","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}