{"record":{"id":"b7bb10ab09dae09b","repo":"vitessio/vitess","slug":"vt13001-b7bb10","errorCode":"VT13001","errorMessage":"offset out of range","messagePattern":"offset out of range","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/planbuilder/operators/hash_join.go","lineNumber":121,"sourceCode":"}\n\nfunc (hj *HashJoin) AddColumn(ctx *plancontext.PlanningContext, reuseExisting bool, addToGroupBy bool, expr *sqlparser.AliasedExpr) int {\n\tif reuseExisting {\n\t\toffset := hj.FindCol(ctx, expr.Expr, false)\n\t\tif offset >= 0 {\n\t\t\treturn offset\n\t\t}\n\t}\n\n\thj.columns.add(expr.Expr)\n\treturn len(hj.columns.columns) - 1\n}\n\nfunc (hj *HashJoin) AddWSColumn(ctx *plancontext.PlanningContext, offset int, underRoute bool) int {\n\thj.planOffsets(ctx)\n\n\tif len(hj.ColumnOffsets) <= offset {\n\t\tpanic(vterrors.VT13001(\"offset out of range\"))\n\t}\n\n\t// check if it already exists\n\twsExpr := weightStringFor(hj.columns.columns[offset].expr)\n\tif index := hj.FindCol(ctx, wsExpr, false); index != -1 {\n\t\treturn index\n\t}\n\n\ti := hj.ColumnOffsets[offset]\n\tout := 0\n\tif i < 0 {\n\t\tout = hj.LHS.AddWSColumn(ctx, FromLeftOffset(i), underRoute)\n\t\tout = ToLeftOffset(out)\n\t} else {\n\t\tout = hj.RHS.AddWSColumn(ctx, FromRightOffset(i), underRoute)\n\t\tout = ToRightOffset(out)\n\t}\n\thj.ColumnOffsets = append(hj.ColumnOffsets, out)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/planbuilder/operators/hash_join.go#L103-L139","documentation":"VT13001 is an internal consistency error thrown by HashJoin.AddWSColumn when the requested column offset is beyond the columns currently planned for the hash join (hj.ColumnOffsets is shorter than the offset). AddWSColumn is supposed to add a weightstring column for an existing output column; asking for a weightstring of a non-existent column means planner bookkeeping is out of sync, so it panics.","triggerScenarios":"Internal planner paths request AddWSColumn with an offset that was never registered via planOffsets - typically a bug in offset planning for queries combining hash joins with ORDER BY/GROUP BY on expressions requiring weightstrings (e.g. collation-sensitive ordering).","commonSituations":"Queries with ORDER BY or comparisons over string columns across a hash join whose collations force weightstring computation; regressions after Vitess upgrades changing offset planning; shouldn't occur for ordinary queries.","solutions":["Reduce the query minimally and check whether removing the ORDER BY/comparison on the weightstring-requiring column avoids the panic","Force a different plan (e.g. add a LIMIT, reorder joins, or set flags that avoid hash join offsets) as a workaround","File a Vitess bug with the query and stack - this is an internal invariant violation, not user input validation"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tif strings.Contains(fmt.Sprint(r), \"VT13001\") || strings.Contains(fmt.Sprint(r), \"offset out of range\") {\n\t\t\terr = vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"hash join offset planning bug: %v\", r)\n\t\t}\n\t}\n}()","preventionTips":["Report minimal reproducers - this is an internal invariant violation","Avoid relying on collation-sensitive ORDER BY across hash joins until tested","Keep Vitess updated; regressions here are fixed quickly upstream"],"tags":["vitess","planbuilder","hash-join","internal-error"],"backgroundTag":"internal-planner-panic","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}