{"record":{"id":"2c48a2a050cfa8f6","repo":"vitessio/vitess","slug":"no-binlog-source-is-defined-for-workflow-s","errorCode":null,"errorMessage":"no binlog source is defined for workflow %s","messagePattern":"no binlog source is defined for workflow (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/workflow/stream_migrator.go","lineNumber":705,"sourceCode":"\t\tstoppedStreams = make(map[string][]*VReplicationStream)\n\t)\n\n\terr := sm.ts.ForAllSources(func(source *MigrationSource) error {\n\t\tshard := source.GetShard().ShardName()\n\t\ttabletStreams := sm.streams[shard]\n\t\tif len(tabletStreams) == 0 {\n\t\t\treturn nil\n\t\t}\n\n\t\t// For intra-keyspace materialize workflows where the source and target are both\n\t\t// the keyspace that is being resharded, we need to wait for those to catchup as\n\t\t// well. New writes have already been blocked on the source, but the materialization\n\t\t// workflow(s) still need to catchup with writes that happened just before writes\n\t\t// were stopped on the source.\n\t\teg, egCtx := errgroup.WithContext(ctx)\n\t\tfor _, vrs := range tabletStreams {\n\t\t\tif vrs.BinlogSource == nil { // Should never happen\n\t\t\t\treturn fmt.Errorf(\"no binlog source is defined for workflow %s\", vrs.Workflow)\n\t\t\t}\n\t\t\tif vrs.WorkflowType == binlogdatapb.VReplicationWorkflowType_Materialize && vrs.BinlogSource.Keyspace == sm.ts.TargetKeyspaceName() {\n\t\t\t\teg.Go(func() error {\n\t\t\t\t\tsourceTablet := source.primary.CloneVT()\n\t\t\t\t\tif sourceTablet.Shard != vrs.BinlogSource.Shard {\n\t\t\t\t\t\tsi, err := sm.ts.TopoServer().GetTabletMapForShard(egCtx, vrs.BinlogSource.GetKeyspace(), vrs.BinlogSource.GetShard())\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor _, tablet := range si {\n\t\t\t\t\t\t\tif tablet.GetType() == topodatapb.TabletType_PRIMARY {\n\t\t\t\t\t\t\t\tsourceTablet = tablet.CloneVT()\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif sourceTablet == nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"no primary tablet found for materialization workflow %s and its stream from the binary log source %s/%s\",","sourceCodeStart":687,"sourceCodeEnd":723,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/workflow/stream_migrator.go#L687-L723","documentation":"In stopSourceStreams (part of the StreamMigrator workflow-migration stop path), each collected VReplicationStream must carry a BinlogSource describing where it replicates from. This error guards against a stream row whose BinlogSource proto is nil when checking whether intra-keyspace materialization workflows need catch-up. The code comments it 'Should never happen' — it indicates a corrupt or improperly parsed vreplication row.","triggerScenarios":"Calling StopStreams (or the migration stop path) where a _vt.vreplication row read from a source shard primary yields a VReplicationStream with a nil BinlogSource — e.g. the BinlogSource field in the row is empty/unparseable, or the read path returned a partially-populated stream struct.","commonSituations":"Corrupted or manually edited _vt.vreplication rows in the backing MySQL database; a bug in a stream-reading code path that fails to populate BinlogSource; rows created outside normal tooling.","solutions":["Inspect the offending stream: `select id, workflow, source from _vt.vreplication` on the affected shard's primary to see if the source (BinlogSource) is empty or malformed.","Cancel/delete the broken vreplication row if it belongs to an abandoned workflow, then recreate the workflow properly (MoveTables/Materialize).","If the row looks valid, this points to a code bug — capture the workflow/tablet details and report/check the Vitess version for known fixes.","Re-run the migration stop after the row is fixed."],"exampleFix":"-- before: row with NULL/empty source\nselect id, workflow, source from _vt.vreplication where workflow='mz1';\n-- after: remove the corrupt row then rebuild the workflow\ndelete from _vt.vreplication where id=<bad_id>;\n-- recreate via vtctldclient Materialize / MoveTables","handlingStrategy":"validation","validationCode":"// Ensure every vreplication row has a non-empty, parseable source\n// SELECT id, workflow FROM _vt.vreplication WHERE source IS NULL OR source = '';\n-- any hit means a corrupt row that will fail migration","typeGuard":"func hasBinlogSource(vrs *workflow.VReplicationStream) bool { return vrs != nil && vrs.BinlogSource != nil }","tryCatchPattern":null,"preventionTips":["Never hand-edit _vt.vreplication rows; use vtctldclient.","Periodically validate stream rows with VExec/SELECT to catch empty source fields early."],"tags":["vitess","vreplication","corrupt-state","internal-invariant"],"backgroundTag":"missing-binlog-source","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}