vitessio/vitess · error

source table %s not found in vschema

Error message

source table %s not found in vschema

What it means

CreateLookupVindex requires the source table to be present in the source keyspace's vschema. When the table entry is missing (and the table is not an internal Vitess operation table), preparation aborts. The vschema entry is needed to read the table's ColumnVindexes and to attach the new lookup vindex.

Source

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

		if err != nil {
			return nil, nil, nil, err
		}
	}
	if targetVSchema.Vindexes == nil {
		targetVSchema.Vindexes = make(map[string]*vschemapb.Vindex)
	}
	if targetVSchema.Tables == nil {
		targetVSchema.Tables = make(map[string]*vschemapb.Table)
	}
	if existing, ok := sourceVSchema.Vindexes[vindexName]; ok {
		if !proto.Equal(existing, vindex) {
			return nil, nil, nil, fmt.Errorf("a conflicting vindex named %s already exists in the source vschema", vindexName)
		}
	}
	sourceVSchemaTable = sourceVSchema.Tables[sourceTableName]
	if sourceVSchemaTable == nil {
		if !schema.IsInternalOperationTableName(sourceTableName) {
			return nil, nil, nil, fmt.Errorf("source table %s not found in vschema", sourceTableName)
		}
	}
	for _, colVindex := range sourceVSchemaTable.ColumnVindexes {
		// For a conflict, the vindex name and column should match.
		if colVindex.Name != vindexName {
			continue
		}
		colName := colVindex.Column
		if len(colVindex.Columns) != 0 {
			colName = colVindex.Columns[0]
		}
		if colName == sourceVindexColumns[0] {
			return nil, nil, nil, fmt.Errorf("ColumnVindex for table %v already exists: %v, please remove it and try again", sourceTableName, colName)
		}
	}

	// Validate against source schema
	sourceShards, err := wr.ts.GetServingShards(ctx, keyspace)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Add a table entry for the source table in the source keyspace vschema (`vtctldclient ApplyVSchema`), even if empty `{}`, then retry
  2. Verify the table name matches exactly (case-sensitive) the key in the vschema Tables map
  3. Confirm you are targeting the correct keyspace

Example fix

// before: table absent from vschema
// after: add the table to the vschema JSON
"tables": {
  "users": {}
}
Defensive patterns

Strategy: validation

Validate before calling

vs, _ := ts.GetVSchema(ctx, keyspace)
if vs.Tables[sourceTableName] == nil && !schema.IsInternalOperationTableName(sourceTableName) {
    return fmt.Errorf("add table %s to the vschema first", sourceTableName)
}

Type guard

func tableInVSchema(vs *vschemapb.Keyspace, table string) bool {
    return vs.Tables != nil && vs.Tables[table] != nil
}

Try / catch

if err := createLookupVindex(...); err != nil {
    if strings.Contains(err.Error(), "not found in vschema") {
        return applyTableToVSchema(ks, table) // then retry
    }
    return err
}

Prevention

When it happens

Trigger: Running CreateLookupVindex for a table that exists in MySQL but has no entry in `sourceVSchema.Tables` — e.g. the keyspace is unsharded with no explicit table config, or the table name in the request doesn't match the vschema key (case or keyspace-qualified name mismatch).

Common situations: Newly created tables never added to the sharded vschema; typos in table names; running against an unsharded keyspace where Tables map was never populated.

Related errors


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