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

  1. Remove or narrow the mirror rule scope so it does not apply to the filtered query
  2. Simplify or remove the WHERE predicate for mirrored queries
  3. 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

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.