vitessio/vitess · error

unknown table %v in schema

Error message

unknown table %v in schema

What it means

While decoding a row event, vstreamer looks up the table in vttablet's schema engine at the stream's position. If the table is absent from the schema and the Filter's FieldEventMode is ERR_ON_MISMATCH, it fails instead of silently skipping the table, alerting the operator that the stream references a table the schema doesn't know.

Source

Thrown at go/vt/vttablet/tabletserver/vstreamer/vstreamer.go:1054

			// the response layer should be using utf-8 as that's the standard -- so we
			// should NOT use utf8mb4 as the collation in MySQL for a JSON column is
			// NULL, meaning there is not one (same as for int) and we should use binary.
			coll = collations.CollationBinaryID
		default: // Use the server defined default for the column's type
			coll = collations.CollationForType(t, vs.se.Environment().CollationEnv().DefaultConnectionCharset())
		}
		fields = append(fields, &querypb.Field{
			Name:    fmt.Sprintf("@%d", i+1),
			Type:    t,
			Charset: uint32(coll),
			Flags:   mysql.FlagsForColumn(t, coll),
		})
	}
	st, err := vs.se.GetTableForPos(vs.ctx, sqlparser.NewIdentifierCS(tm.Name), replication.EncodePosition(vs.pos))
	if err != nil {
		if vs.filter.FieldEventMode == binlogdatapb.Filter_ERR_ON_MISMATCH {
			log.Info("No schema found for table " + tm.Name)
			return nil, fmt.Errorf("unknown table %v in schema", tm.Name)
		}
		return fields, nil
	}

	if len(st.Fields) < len(tm.Types) {
		if vs.filter.FieldEventMode == binlogdatapb.Filter_ERR_ON_MISMATCH {
			log.Info("Cannot determine columns for table " + tm.Name)
			return nil, fmt.Errorf("cannot determine table columns for %s: event has %v, schema has %v", tm.Name, tm.Types, st.Fields)
		}
		return fields, nil
	}

	// Check if the schema returned by schema.Engine is compatible with the row.
	// If not then we rely on the TableMap event alone. This will prevent us from
	// being able to handle filters with colum names (in planbuilder.findColumn()).
	for i := range tm.Types {
		if !sqltypes.AreTypesCompatible(fields[i].Type, st.Fields[i].Type) {
			return fields, nil

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Reload the vttablet schema (schema reload) so the table is visible
  2. Change the filter FieldEventMode away from ERR_ON_MISMATCH if skipping unknown tables is acceptable
  3. Re-create the table or restore it if the drop was unintentional
  4. Restart the stream from a position after the table was dropped
Defensive patterns

Strategy: fallback

Validate before calling

// Before streaming, confirm the table exists in the tablet schema:
// SHOW TABLES LIKE '<table>';  -- and ensure vttablet schema is loaded

Try / catch

if strings.Contains(err.Error(), "unknown table") && strings.Contains(err.Error(), "in schema") {
    // either reload schema and retry, or adjust Filter.FieldEventMode to tolerate misses
}

Prevention

When it happens

Trigger: buildTableColumns calls vs.se.GetTableForPos and receives an error while vs.filter.FieldEventMode == binlogdatapb.Filter_ERR_ON_MISMATCH; in other modes it would just return the fields gathered so far.

Common situations: Streaming rows for a table that was dropped or renamed mid-stream; keyspace/shard filtering (tables outside the filter) with ERR_ON_MISMATCH configured; stale or not-yet-loaded schema in vttablet.

Related errors


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