vitessio/vitess · error

unrecognized statement: %s

Error message

unrecognized statement: %s

What it means

generateInserts parses each TableSettings SourceExpression expecting a plain SELECT statement to use as the copy filter. If the statement parses but is not a *sqlparser.Select (e.g. INSERT, UPDATE, SET, or another statement type), it fails with 'unrecognized statement'.

Source

Thrown at go/vt/wrangler/materializer.go:1362

		}
		for _, ts := range mz.ms.TableSettings {
			rule := &binlogdatapb.Rule{
				Match: ts.TargetTable,
			}

			if ts.SourceExpression == "" {
				bls.Filter.Rules = append(bls.Filter.Rules, rule)
				continue
			}

			// Validate non-empty query.
			stmt, err := mz.wr.env.Parser().Parse(ts.SourceExpression)
			if err != nil {
				return "", err
			}
			sel, ok := stmt.(*sqlparser.Select)
			if !ok {
				return "", fmt.Errorf("unrecognized statement: %s", ts.SourceExpression)
			}
			filter := ts.SourceExpression

			if !keyRangesEqual && mz.targetVSchema.Keyspace.Sharded && mz.targetVSchema.Tables[ts.TargetTable].Type != vindexes.TypeReference {
				cv, err := vindexes.FindBestColVindex(mz.targetVSchema.Tables[ts.TargetTable])
				if err != nil {
					return "", err
				}
				mappedCols := make([]*sqlparser.ColName, 0, len(cv.Columns))
				for _, col := range cv.Columns {
					colName, err := matchColInSelect(col, sel)
					if err != nil {
						return "", err
					}
					mappedCols = append(mappedCols, colName)
				}
				subExprs := make([]sqlparser.Expr, 0, len(mappedCols)+2)
				for _, mappedCol := range mappedCols {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Change SourceExpression to a single plain SELECT statement, e.g. `select * from t where col = 'x'`
  2. Remove any leading/trailing statements, semicolons, or non-select clauses
  3. Verify with the sqlparser or by running the select manually on the source keyspace

Example fix

// before
{"sourceExpression":"insert into t select * from s"}
// after
{"sourceExpression":"select * from s"}
Defensive patterns

Strategy: validation

Validate before calling

stmt, err := parser.Parse(sourceExpression)
if err != nil { return err }
if _, ok := stmt.(*sqlparser.Select); !ok {
    return fmt.Errorf("SourceExpression must be a SELECT, got %T", stmt)
}

Type guard

func isSelectStmt(p *sqlparser.Parser, expr string) bool {
    s, err := p.Parse(expr)
    _, ok := s.(*sqlparser.Select)
    return err == nil && ok
}

Try / catch

if err := workflow.Start(ctx); err != nil {
    if strings.Contains(err.Error(), "unrecognized statement") {
        // fix SourceExpression to a plain SELECT and retry
    }
}

Prevention

When it happens

Trigger: MaterializeSettings.TableSettings.SourceExpression set to a non-SELECT statement, or to an unparsable-in-select-position construct; programmatic use of MoveTables/Materialize APIs with hand-written SourceExpression values.

Common situations: Users pasting full `INSERT INTO ... SELECT ...` or `SELECT ... INTO` statements into filter/SourceExpression config; using comments or multiple statements; older configs that stored filters in a different format.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/6c145068f25a9f5d. Report an issue: GitHub.