vitessio/vitess · error

unsupported construct: %v

Error message

unsupported construct: %v

What it means

Returned by vreplication controller plan building when the statement contains a construct the planner cannot translate into a vreplication plan, wrapping or naming the unsupported construct.

Source

Thrown at go/vt/vttablet/tabletmanager/vreplication/controller_plan.go:189

	tableName, err := ins.Table.TableName()
	if err != nil {
		return nil, err
	}
	if tableName.Qualifier.String() != sidecar.GetName() && tableName.Qualifier.String() != sidecar.DefaultName {
		return nil, fmt.Errorf("invalid database name: %s", tableName.Qualifier.String())
	}
	switch tableName.Name.String() {
	case reshardingJournalTableName:
		return &controllerPlan{
			opcode: reshardingJournalQuery,
		}, nil
	case vreplicationTableName:
		// no-op
	default:
		return nil, fmt.Errorf("invalid table name: %s", tableName.Name.String())
	}
	if ins.Action != sqlparser.InsertAct {
		return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(ins))
	}
	if ins.Ignore {
		return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(ins))
	}
	if ins.Partitions != nil {
		return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(ins))
	}
	if ins.OnDup != nil {
		return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(ins))
	}
	rows, ok := ins.Rows.(sqlparser.Values)
	if !ok {
		return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(ins))
	}
	idPos := 0
	if len(ins.Columns) != 0 {
		idPos = -1
		for i, col := range ins.Columns {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Rewrite as a plain `INSERT INTO _vt.vreplication ...`.
  2. Use `update _vt.vreplication set ... where id=...` instead of REPLACE to modify existing rows.
  3. Ensure unique ids so plain INSERT succeeds (vreplication ids are explicit, not auto-increment).

Example fix

// before
replace into _vt.vreplication(id, message) values (1, 'x')
// after
insert into _vt.vreplication(id, message) values (1, 'x')
Defensive patterns

Strategy: validation

Validate before calling

if strings.HasPrefix(strings.ToUpper(stmt), "REPLACE ") {
    return fmt.Errorf("REPLACE not supported by vreplication engine; use INSERT or UPDATE")
}

Try / catch

plan, err := buildInsertPlan(ins, sidecar)
if err != nil && strings.Contains(err.Error(), "unsupported construct") {
    return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "plain INSERT only; rewrite REPLACE statements")
}

Prevention

When it happens

Trigger: A `REPLACE INTO _vt.vreplication ...` statement (or other non-InsertAct action) passed to the vreplication engine's exec path.

Common situations: Using MySQL's REPLACE INTO as a shortcut for upsert; generated scripts using REPLACE; translation of application SQL into vexec without adjusting syntax.

Related errors


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