vitessio/vitess · error · VitessError
VT13001
VT13001
Error message
VT13001: [BUG] not supported
What it means
VT13001 internal-bug panic thrown by PercentBasedMirror.AddPredicate. Mirror (percent-based mirroring of traffic) does not support receiving pushed-down predicates through the operator API — predicates must be handled before/around the mirror operator. Hitting it means the planner tried to push a predicate into a mirrored query, which the feature never supported.
Source
Thrown at go/vt/vtgate/planbuilder/operators/mirror.go:63
return &PercentBasedMirror{
binaryOperator: newBinaryOp(operator, target),
Percent: percent,
}
}
// Clone will return a copy of this operator, protected so changed to the original will not impact the clone
func (m *PercentBasedMirror) Clone(inputs []Operator) Operator {
cloneMirror := *m
cloneMirror.SetInputs(inputs)
return &cloneMirror
}
// AddPredicate is used to push predicates. It pushed it as far down as is possible in the tree.
// If we encounter a join and the predicate depends on both sides of the join, the predicate will be split into two parts,
// where data is fetched from the LHS of the join to be used in the evaluation on the RHS
// TODO: we should remove this and replace it with rewriters
func (m *PercentBasedMirror) AddPredicate(*plancontext.PlanningContext, sqlparser.Expr) Operator {
panic(vterrors.VT13001("not supported"))
}
func (m *PercentBasedMirror) AddColumn(*plancontext.PlanningContext, bool, bool, *sqlparser.AliasedExpr) int {
panic(vterrors.VT13001("not supported"))
}
func (m *PercentBasedMirror) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) int {
return m.Operator().FindCol(ctx, expr, underRoute)
}
func (m *PercentBasedMirror) GetColumns(ctx *plancontext.PlanningContext) []*sqlparser.AliasedExpr {
return m.Operator().GetColumns(ctx)
}
func (m *PercentBasedMirror) GetSelectExprs(ctx *plancontext.PlanningContext) []sqlparser.SelectExpr {
return m.Operator().GetSelectExprs(ctx)
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Remove or narrow the mirror rule scope so it does not apply to the filtered query
- Simplify or remove the WHERE predicate for mirrored queries
- File a bug with the query and mirror rule; mirroring + predicate pushdown is unsupported
Example fix
// before: mirror rule matches the queried table
"mirror_rules": [{"from_table": "t", "to_table": "t_m", "percent": 50}]
// after: restrict mirror rule or drop the predicate path
// remove the rule for tables queried with WHERE filters Defensive patterns
Strategy: validation
Validate before calling
// ensure no mirror rule applies to tables queried with WHERE predicates
const mirrored = mirrorRules.some(r => r.from_table === queriedTable);
if (mirrored && hasWherePredicate(query)) console.warn('unsupported: mirrored query with predicate'); Type guard
null
Try / catch
null
Prevention
- Do not combine mirror rules with filtered queries
- Mirror only simple point reads
- Keep mirror rules narrowly scoped by table
- Test mirrored queries after upgrades
When it happens
Trigger: A query planned against a table with a percent-based mirror VSchema rule while a WHERE-clause predicate is pushed down and reaches the PercentBasedMirror operator via AddPredicate.
Common situations: Combining mirror rules in the VSchema with non-trivial SELECT ... WHERE queries; enabling mirroring and then upgrading Vitess so a new planner phase pushes predicates further down than before.
Related errors
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/60c816b633f78006.
Report an issue: GitHub.