{"record":{"id":"2d3632aeb560c1c7","repo":"vitessio/vitess","slug":"unexpected-event-on-table-s","errorCode":null,"errorMessage":"unexpected event on table %s","messagePattern":"unexpected event on table (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vreplication/vplayer.go","lineNumber":411,"sourceCode":"\t\t\t\t\"vreplication: malformed row change with no row images in event for table %s\", tableName)\n\t\tcase change.GetBefore() != nil && change.GetAfter() == nil:\n\t\t\tinsertsOnly = false\n\t\tcase change.GetBefore() == nil && change.GetAfter() != nil:\n\t\t\tdeletesOnly = false\n\t\tdefault: // Update-shaped (both images).\n\t\t\tdeletesOnly, insertsOnly = false, false\n\t\t}\n\t}\n\treturn deletesOnly, insertsOnly, nil\n}\n\nfunc (vp *vplayer) applyRowEvent(ctx context.Context, rowEvent *binlogdatapb.RowEvent) error {\n\tif err := vp.updateFKCheck(ctx, rowEvent.Flags); err != nil {\n\t\treturn err\n\t}\n\ttplan := vp.tablePlans[rowEvent.TableName]\n\tif tplan == nil {\n\t\treturn fmt.Errorf(\"unexpected event on table %s\", rowEvent.TableName)\n\t}\n\tapplyFunc := func(sql string) (*sqltypes.Result, error) {\n\t\tstart := time.Now()\n\t\tqr, err := vp.query(ctx, sql)\n\t\tvp.vr.stats.QueryCount.Add(vp.phase, 1)\n\t\tvp.vr.stats.QueryTimings.Record(vp.phase, start)\n\t\treturn qr, err\n\t}\n\n\tif vp.batchMode && len(rowEvent.RowChanges) > 1 {\n\t\tdeletesOnly, insertsOnly, err := bulkApplicableShapes(rowEvent.TableName, rowEvent.RowChanges)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// If we have multiple delete row events for a table with a single PK column\n\t\t// then we can perform a simple bulk DELETE using an IN clause.\n\t\tif deletesOnly && tplan.MultiDelete != nil {\n\t\t\t_, err := tplan.applyBulkDeleteChanges(rowEvent.RowChanges, applyFunc, vp.vr.dbClient.maxBatchSize)","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/vplayer.go#L393-L429","documentation":"vplayer received a RowEvent for a table that has no entry in vp.tablePlans — the plan map built from the workflow's filter rules when the stream started. Since there is no table plan, the row change cannot be transformed/applied to the target, so the event is rejected as unexpected.","triggerScenarios":"A RowEvent arrives (after updateFKCheck succeeds) whose rowEvent.TableName is absent from vp.tablePlans — typically because the table was created/altered on the source after the stream began, or the filter/keyspace/table mismatch means the plan was never built for it.","commonSituations":"DDL on the source adding a new table mid-workflow that the filter unintentionally matches (e.g. broad /.* rule); keyspace or table name case-mismatch; source shard reconfigured so events from an unfiltered table leak in; stale stream state after filter changes without restarting the workflow.","solutions":["Confirm the workflow filter rules cover exactly the tables being streamed, and that the event table should really be included","If the table is new on the source, restart/re-create the workflow so tablePlans are rebuilt including it","Check for table name case or keyspace mismatches between source and filter rules","If the event should be excluded, tighten the filter rules (no overly broad patterns) and restart the stream"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before starting/restarting the workflow, confirm every streamed table matches a filter rule\nfor _, tbl := range sourceTables {\n    if !matchesAnyRule(workflowFilter, tbl) && !explicitlyExcluded(tbl) {\n        // tighten or broaden rules so tablePlans cover exactly the intended set\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := applyEvent(ctx, ev); err != nil && strings.Contains(err.Error(), \"unexpected event on table\") {\n    // restart workflow to rebuild tablePlans including/excluding that table\n}","preventionTips":["Restart the workflow after changing filter rules or after adding tables on the source","Avoid overly broad filter patterns (e.g. /.*) that accidentally catch new tables","Watch for table-name case mismatches between source and filter rules","Apply source DDL deliberately during active workflows and review filter impact"],"tags":["vreplication","row-event","table-plan","filter"],"backgroundTag":"unexpected-row-event-table","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}