{"record":{"id":"62b55f3960eb9e66","repo":"vitessio/vitess","slug":"cannot-update-vreplication-table-affected-v-rows","errorCode":null,"errorMessage":"cannot update vreplication table, affected %v rows","messagePattern":"cannot update vreplication table, affected (.+?) rows","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/binlog/binlogplayer/binlog_player.go","lineNumber":531,"sourceCode":"//     with it, and set ReplicationLagSeconds to now() - transaction_timestamp\n//   - otherwise (the statements are probably filtered out), we leave\n//     transaction_timestamp alone (keeping the old value), and we don't\n//     change ReplicationLagSeconds\nfunc (blp *BinlogPlayer) writeRecoveryPosition(tx *binlogdatapb.BinlogTransaction) error {\n\tposition, err := DecodePosition(tx.EventToken.Position)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tnow := time.Now().Unix()\n\tupdateRecovery := GenerateUpdatePos(blp.uid, position, now, tx.EventToken.Timestamp, blp.blplStats.CopyRowCount.Get(), false)\n\n\tqr, err := blp.exec(updateRecovery)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error %v in writing recovery info %v\", err, updateRecovery)\n\t}\n\tif qr.RowsAffected != 1 {\n\t\treturn fmt.Errorf(\"cannot update vreplication table, affected %v rows\", qr.RowsAffected)\n\t}\n\n\t// Update position after successful write.\n\tblp.position = position\n\tblp.blplStats.SetLastPosition(blp.position)\n\tif tx.EventToken.Timestamp != 0 {\n\t\tblp.blplStats.ReplicationLagSeconds.Store(now - tx.EventToken.Timestamp)\n\t}\n\treturn nil\n}\n\nfunc (blp *BinlogPlayer) setVReplicationState(state binlogdatapb.VReplicationWorkflowState, message string) error {\n\tif message != \"\" {\n\t\tblp.blplStats.History.Add(&StatsHistoryRecord{\n\t\t\tTime:    time.Now(),\n\t\t\tMessage: message,\n\t\t})\n\t}","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/binlog/binlogplayer/binlog_player.go#L513-L549","documentation":"Thrown by writeRecoveryPosition when the UPDATE of the _vt.vreplication row executes successfully but affects 0 rows instead of 1 — meaning no row exists for this player's uid. The player then rolls back the enclosing transaction (via the caller), so neither data nor position is committed.","triggerScenarios":"The _vt.vreplication row with id=blp.uid was deleted concurrently (stream cancelled externally, workflow removed) while the player was still applying events, or the row was never inserted for this uid.","commonSituations":"Operator ran `vtctldclient Workflow ... delete` or VReplicationExec delete while the stream was mid-transaction; target keyspace re-sharded/pruned old vreplication rows; race between workflow removal and tablet shutdown.","solutions":["Check if the vreplication row still exists: `SELECT id, state FROM _vt.vreplication WHERE id=<uid>`; if deleted intentionally, stop the player — the workflow is gone.","If deleted accidentally, recreate the workflow/stream to insert a new row and resync.","Avoid deleting vreplication rows while streams are active; cancel the workflow first and wait for state=Stopped.","Investigate concurrent automation (shard pruning scripts) racing with active streams."],"exampleFix":"// before: deleting row while stream is live\n//   DELETE FROM _vt.vreplication WHERE id=1; -- row gone, update hits 0 rows\n// after: stop the stream first, then remove\n//   vtctldclient VReplicationExec <keyspace> \"update _vt.vreplication set state='Stopped' where id=1\"\n//   # then delete after the player exits","handlingStrategy":"validation","validationCode":"// before each stream start (and periodically), confirm the row exists\nvar n int\nif err := targetDB.QueryRow(\n    \"SELECT COUNT(*) FROM _vt.vreplication WHERE id = ?\", uid,\n).Scan(&n); err != nil || n != 1 {\n    return fmt.Errorf(\"vreplication row id=%d missing; workflow was removed or never created\", uid)\n}","typeGuard":null,"tryCatchPattern":"err := binlogplayer.ApplyBinlogEvents(ctx, blp)\nif err != nil && strings.Contains(err.Error(), \"cannot update vreplication table\") {\n    // row deleted concurrently — do NOT blindly restart; check workflow intent\n    log.Error(\"_vt.vreplication row vanished mid-stream; workflow was likely deleted\")\n    return err\n}","preventionTips":["Stop the workflow (state='Stopped') and wait for the player to exit before deleting rows","Audit automation scripts that prune _vt.vreplication rows for races with active streams","Use vtctldclient workflow commands rather than raw SQL for lifecycle changes"],"tags":["vreplication","recovery-position","race-condition","row-missing"],"backgroundTag":"vreplication-row-missing","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}