vitessio/vitess · error
plan not found for table: %s, current plans are: %#v
Error message
plan not found for table: %s, current plans are: %#v
What it means
vcopier.copyTable processes a binlog RowEvent for a table being copied, but the copy plan (built from the workflow's Filter) has no entry under plan.TargetTables for that table name. The controller only expects events for tables it planned to copy, so an unmatched table name indicates a plan/event mismatch and the copy phase fails.
Source
Thrown at go/vt/vttablet/tabletmanager/vreplication/vcopier.go:395
// copyTable performs the synchronized copy of the next set of rows from
// the current table being copied. Each packet received is transactionally
// committed with the lastpk. This allows for consistent resumability.
func (vc *vcopier) copyTable(ctx context.Context, tableName string, copyState map[string]*sqltypes.Result) error {
defer vc.vr.dbClient.Rollback()
defer vc.vr.stats.PhaseTimings.Record("copy", time.Now())
defer vc.vr.stats.CopyLoopCount.Add(1)
log.Info(fmt.Sprintf("Copying table %s, lastpk: %v", tableName, copyState[tableName]))
plan, err := vc.vr.buildReplicatorPlan(vc.vr.source, vc.vr.colInfoMap, nil, vc.vr.stats, vc.vr.vre.env.CollationEnv(), vc.vr.vre.env.Parser())
if err != nil {
return err
}
initialPlan, ok := plan.TargetTables[tableName]
if !ok {
return fmt.Errorf("plan not found for table: %s, current plans are: %#v", tableName, plan.TargetTables)
}
// Save the controller-level context before applying the copy phase
// duration timeout to it. Its cancellation means that the controller
// is stopping -- because the workflow is being stopped or deleted, or
// the engine is closing -- and any in-flight post copy action must
// then be interrupted, whereas an elapsed copy phase duration must
// not interrupt it.
stopCtx := ctx
ctx, cancel := context.WithTimeout(ctx, vc.vr.workflowConfig.CopyPhaseDuration)
defer cancel()
var lastpkpb *querypb.QueryResult
if lastpkqr := copyState[tableName]; lastpkqr != nil {
lastpkpb = sqltypes.ResultToProto3(lastpkqr)
}
rowsCopiedTicker := time.NewTicker(rowsCopiedUpdateInterval)View on GitHub (pinned to 01a25a7d17)
Solutions
- Check the workflow's TargetTables in the plan log and confirm the offending table should be copied
- Update the workflow Filter send-rules to explicitly include or exclude the table, then restart the copy phase
- If the table was created mid-copy, recreate the workflow so the plan includes it
- Verify consistent table name casing between source MySQL and the filter rules
Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the table is covered by the workflow filter before copy -- compare source table list against the workflow's TargetTables / send-rules
Try / catch
if err := vc.copyNext(ctx); err != nil {
if strings.Contains(err.Error(), "plan not found for table") {
// table appeared mid-copy or filter mismatch: rebuild workflow
// reload the plan / recreate the workflow with corrected rules
}
return err
} Prevention
- Create tables on the source before or after the copy phase, not during
- Use precise send-rule matches rather than broad wildcards
- Keep table name casing consistent between MySQL and filter rules
- Recreate the workflow after schema changes on copied tables
When it happens
Trigger: A TableMap/RowEvent arrives during the copy phase for a table not in the workflow's TargetTables — e.g. the source schema gained a new table after planning, a send-rule match is broader than the planned tables, or table name casing differs.
Common situations: A table is created on the source mid-copy; filter send-rule wildcards (e.g. 't.*') match more tables than the plan enumerated; keyspace/table name case mismatch between MySQL and Vitess.
Related errors
- unexpected: there are no tables to copy
- work queue is not open
- CopyAll was interrupted due to context expiration
- cannot migrate while vreplication streams in source shards a
- primary key column %v not found in table's select filter or
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/f95bc475a6785924.
Report an issue: GitHub.