vitessio/vitess · error

source and target table names must match for copying schema:

Error message

source and target table names must match for copying schema: %v vs %v

What it means

When CreateDdl is 'copy'-style and the TableSettings has a non-empty SourceExpression, the materializer verifies the SELECT's source table name equals the target table name, because schema copy assumes source and target are the same table. A mismatch (e.g. a WHERE/join or renamed table) makes copying ambiguous and fails.

Source

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

				// and we have found use cases where user just has a replica (no primary) in the source keyspace
				sourceDDLs, err = mz.getSourceTableDDLs(ctx)
			}
			mu.Unlock()
			if err != nil {
				log.Error("Error getting DDLs of source tables: " + err.Error())
				return err
			}

			createDDL := ts.CreateDdl
			if createDDL == createDDLAsCopy || createDDL == createDDLAsCopyDropConstraint || createDDL == createDDLAsCopyDropForeignKeys {
				if ts.SourceExpression != "" {
					// Check for table if non-empty SourceExpression.
					sourceTableName, err := mz.wr.env.Parser().TableFromStatement(ts.SourceExpression)
					if err != nil {
						return err
					}
					if sourceTableName.Name.String() != ts.TargetTable {
						return fmt.Errorf("source and target table names must match for copying schema: %v vs %v", sqlparser.String(sourceTableName), ts.TargetTable)
					}
				}

				ddl, ok := sourceDDLs[ts.TargetTable]
				if !ok {
					return fmt.Errorf("source table %v does not exist", ts.TargetTable)
				}

				if createDDL == createDDLAsCopyDropConstraint {
					strippedDDL, err := stripTableConstraints(ddl, mz.wr.env.Parser())
					if err != nil {
						return err
					}

					ddl = strippedDDL
				}

				if createDDL == createDDLAsCopyDropForeignKeys {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Rename TargetTable to match the source table name in the SourceExpression
  2. Or change CreateDdl to an explicit CREATE TABLE string (not 'copy') when the target table name intentionally differs
  3. Or empty the SourceExpression if schema-only copy was intended

Example fix

// before (MaterializeSettings in json)
{"targetTable":"dst","sourceExpression":"select * from src","createDdl":"copy"}
// after: either match names or give explicit DDL
{"targetTable":"src","sourceExpression":"select * from src where id>0","createDdl":"copy"}
{"targetTable":"dst","sourceExpression":"select * from src","createDdl":"CREATE TABLE dst (...)"}
Defensive patterns

Strategy: validation

Validate before calling

for _, ts := range settings.TableSettings {
    if ts.CreateDdl == "copy" && ts.SourceExpression != "" {
        t, err := parser.TableFromStatement(ts.SourceExpression)
        if err != nil { return err }
        if t.Name.String() != ts.TargetTable {
            return fmt.Errorf("create-ddl=copy requires matching names: %s vs %s", t.Name, ts.TargetTable)
        }
    }
}

Prevention

When it happens

Trigger: MaterializeSettings.TableSettings with CreateDdl=copy and a SourceExpression whose parsed FROM table differs from TargetTable, e.g. `select ... from src_table` with TargetTable `dst_table`, or a select against a joined/derived table.

Common situations: Users configuring a materialized view (filter/transform) while accidentally leaving create-ddl='copy' from a previous same-name MoveTables config; copy-paste of TableSettings across workflows with renamed tables.

Related errors


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