vitessio/vitess · error
VT13001
VT13001
Error message
a derived table should never be a routed table
What it means
VT13001 is Vitess' internal-error code. While rewriting a routed table reference, the planner expects the query table's alias expression to be a plain TableName; if it is a derived table (subquery in FROM), that invariant is broken, meaning a routed table is being defined via a derived table expression — never valid.
Source
Thrown at go/vt/vtgate/planbuilder/operators/route.go:450
return nil
}
// createRouteFromTable creates a route from the given VSchema table.
func createRouteFromVSchemaTable(
ctx *plancontext.PlanningContext,
queryTable *QueryTable,
vschemaTable *vindexes.BaseTable,
planAlternates bool,
targeted Routing,
) *Route {
if vschemaTable.Name.String() != queryTable.Table.Name.String() {
// we are dealing with a routed table
queryTable = queryTable.Clone()
name := queryTable.Table.Name
queryTable.Table.Name = vschemaTable.Name
astTable, ok := queryTable.Alias.Expr.(sqlparser.TableName)
if !ok {
panic(vterrors.VT13001("a derived table should never be a routed table"))
}
realTableName := sqlparser.NewIdentifierCS(vschemaTable.Name.String())
astTable.Name = realTableName
if queryTable.Alias.As.IsEmpty() {
// if the user hasn't specified an alias, we'll insert one here so the old table name still works
queryTable.Alias.As = sqlparser.NewIdentifierCS(name.String())
}
}
plan := &Route{
unaryOperator: newUnaryOp(&Table{
QTable: queryTable,
VTable: vschemaTable,
}),
}
// We create the appropriate Routing struct here, depending on the type of table we are dealing with.
var routing Routing
if targeted != nil {View on GitHub (pinned to 01a25a7d17)
Solutions
- Check the vschema: the routed table's target should be a real table, not something resolvable through a derived table
- Rewrite the query to reference the underlying table directly instead of via a subquery alias
- File a bug with query + vschema if this occurs with a valid configuration
Example fix
// vschema before
"route_target": {"type": "routed", "target": "..."} // resolves via subquery
// after
"real_table": {"type": "routed", "target": "ks.real_table"} // point at a concrete table Defensive patterns
Strategy: validation
Validate before calling
// validate vschema routed tables resolve to concrete tables, not subquery aliases // before deploying, run the query through vtexplain / vtgate with the vschema
Prevention
- Keep routed_table targets pointing at concrete tables
- Test vschema changes with representative queries (including subqueries) in vtexplain
- Report VT13001 with query + vschema — it indicates a planner bug
When it happens
Trigger: A vschema defines a routed table whose resolution path encounters a derived-table (aliased subquery) AST node instead of a TableName in createRouteFromVSchemaTable.
Common situations: Misconfigured vschema routed_table entries conflicting with subquery-based queries; planner bugs where a routed table resolves through a derived table.
Related errors
- VT13001
- value must be either a float64 (interpreted as seconds) or a
- flagutil: NewOptionalFlag requires a non-nil parse function
- flagutil: OptionalFlagValue has no parse function; use a con
- one or two tables must be specified
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/76fc69192b4206d2.
Report an issue: GitHub.