vitessio/vitess · error
ErrUnsupportedQuery
ErrUnsupportedQuery
Error message
%w: %s
What it means
VReplicationQueryPlanner.PlanQuery only supports a fixed set of statement types (SELECT, UPDATE, DELETE etc.); any other statement (INSERT, DDL, SET, SHOW, etc.) results in ErrUnsupportedQuery. The planner then wraps the error with the offending statement's SQL text so the developer can see exactly which query was rejected.
Source
Thrown at go/vt/vtctl/workflow/vexec/query_planner.go:134
//
// For DELETE queries, USING, PARTITION, ORDER BY, and LIMIT clauses are not
// supported.
func (planner *VReplicationQueryPlanner) PlanQuery(stmt sqlparser.Statement) (plan QueryPlan, err error) {
switch stmt := stmt.(type) {
case *sqlparser.Select:
plan, err = planner.planSelect(stmt)
case *sqlparser.Insert:
err = ErrUnsupportedQuery
case *sqlparser.Update:
plan, err = planner.planUpdate(stmt)
case *sqlparser.Delete:
plan, err = planner.planDelete(stmt)
default:
err = ErrUnsupportedQuery
}
if err != nil {
return nil, fmt.Errorf("%w: %s", err, sqlparser.String(stmt))
}
return plan, nil
}
// QueryParams is part of the QueryPlanner interface. A VReplicationQueryPlanner
// will attach the following WHERE clauses iff (a) DBName, Workflow are set,
// respectively, and (b) db_name and workflow do not appear in the original
// query's WHERE clause:
//
// WHERE (db_name = {{ .DBName }} AND)? (workflow = {{ .Workflow }} AND)? {{ .OriginalWhere }}
func (planner *VReplicationQueryPlanner) QueryParams() QueryParams {
return QueryParams{
DBName: planner.dbname,
DBNameColumn: "db_name",
Workflow: planner.workflow,
WorkflowColumn: "workflow",
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Only pass SELECT/UPDATE/DELETE statements supported by VReplicationQueryPlanner to PlanQuery
- Rewrite INSERT or DDL work using the appropriate Vitess APIs (e.g. vtctld commands) instead of this planner
- Check the wrapped SQL in the error and route unsupported statements elsewhere in your tooling
Example fix
// before
plan, err := planner.PlanQuery(ctx, insertStmt) // unsupported
// after
switch stmt.(type) {
case *sqlparser.Select, *sqlparser.Update, *sqlparser.Delete:
plan, err = planner.PlanQuery(ctx, stmt)
default:
return fmt.Errorf("statement type not supported by VReplicationQueryPlanner")
} Defensive patterns
Strategy: validation
Validate before calling
switch stmt.(type) {
case *sqlparser.Select, *sqlparser.Update, *sqlparser.Delete:
// supported
default:
return fmt.Errorf("statement type %T unsupported by VReplicationQueryPlanner", stmt)
} Type guard
func isPlannableStatement(stmt sqlparser.Statement) bool {
switch stmt.(type) {
case *sqlparser.Select, *sqlparser.Update, *sqlparser.Delete:
return true
}
return false
} Try / catch
plan, err := planner.PlanQuery(ctx, stmt)
if errors.Is(err, vexec.ErrUnsupportedQuery) {
log.Warnf("skipping unsupported statement: %v", err)
return nil
} Prevention
- Filter or whitelist statement types before handing SQL to PlanQuery
- Parse and inspect statements with sqlparser before planning
- Route DDL/INSERT work to the appropriate Vitess tooling (vtctld, vtgate) instead
When it happens
Trigger: Calling PlanQuery with a parsed statement that hits the planner's default case — any statement type other than the supported SELECT/UPDATE/DELETE forms (e.g. INSERT, CREATE/ALTER TABLE, SET, SHOW).
Common situations: Passing user-supplied or migration SQL that includes INSERTs or DDL to a VReplication workflow query path; automating workflows over arbitrary SQL scripts; typos routing the wrong statement to the planner.
Related errors
- ErrUnsupportedQueryConstruct
- ErrCannotUpdateImmutableColumn
- --batch-size only allowed when all queries are CREATE TABLE|
- query not supported by vexec
- unsupported multi-table usage
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/c08eae35054f209c.
Report an issue: GitHub.