vitessio/vitess · error
no completed or stopped vdiff found for UUID %s on tablet %s
Error message
no completed or stopped vdiff found for UUID %s on tablet %s
What it means
When resuming, Vitess first tries to resume a completed/stopped vdiff; if no rows are affected it attempts to start (resume a never-started) vdiff, and if that also affects 0 rows, neither a completed/stopped nor an unstarted record matches the UUID, so it errors. The UUID exists conceptually but is not in a resumable state on this tablet.
Source
Thrown at go/vt/vttablet/tabletmanager/vdiff/action.go:265
if err != nil {
return 0, err
}
if qr, err = dbClient.ExecuteFetch(query, 1); err != nil {
return 0, err
}
return qr.RowsAffected, nil
}
rowsAffected, err := execResume(sqlResumeVDiff)
if err != nil {
return err
}
if rowsAffected == 0 { // See if it's a vdiff that was never started
rowsAffected, err := execResume(sqlStartVDiff)
if err != nil {
return err
}
if rowsAffected == 0 {
return fmt.Errorf("no completed or stopped vdiff found for UUID %s on tablet %s",
req.VdiffUuid, topoproto.TabletAliasString(vde.thisTablet.Alias))
}
}
}
resp.VdiffUuid = req.VdiffUuid
qr, err = vde.getVDiffByID(ctx, dbClient, resp.Id)
if err != nil {
return err
}
vdiffRecord := qr.Named().Row()
if vdiffRecord == nil {
return fmt.Errorf("unable to %s vdiff for UUID %s as it was not found on tablet %v (%w)",
action, req.VdiffUuid, topoproto.TabletAliasString(vde.thisTablet.Alias), err)
}
if action == ResumeAction {
// Use the existing options from the vdiff record.
options = optionsZeroValView on GitHub (pinned to 01a25a7d17)
Solutions
- Run vdiff show to check the current state of the UUID on this tablet
- If it's already running, wait or stop it instead of resuming
- If it's in a bad state, delete it and create a fresh vdiff
- Ensure you're targeting the tablet that actually holds the record
Example fix
// before vtctldclient VDiff resume --uuid xyz // state=running // after vtctldclient VDiff show --uuid xyz // inspect state vtctldclient VDiff delete --uuid xyz vtctldclient VDiff create && vtctldclient VDiff resume
Defensive patterns
Strategy: validation
Validate before calling
qr, _ := dbClient.ExecuteFetch("SELECT state FROM _vt.vdiff_tablet WHERE uuid=?", 1, true)
if len(qr.Rows) == 0 { return errors.New("no such vdiff") }
state, _ := qr.Named().Row()["state"].ToString()
if state != "completed" && state != "stopped" { return fmt.Errorf("non-resumable state: %s", state) } Try / catch
if strings.Contains(err.Error(), "no completed or stopped vdiff found") {
// inspect state; delete and re-create if unrecoverable
} Prevention
- Check vdiff show state before resuming
- Never resume while a vdiff is running
- Clean up cancelled vdiffs and create fresh ones
When it happens
Trigger: vdiff resume where the UUID's row is in a non-resumable state (already running/errored/cancelled) or missing on the tablet — both UPDATEs (resume and start) matched 0 rows in handleCreateResumeAction.
Common situations: Resuming a vdiff that is currently running; resuming one that was cancelled or completed and cleaned; using a UUID that was never created on this specific tablet; repeated resume after the record transitioned states.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- VDiff not implemented in vtcombo
- there are no cells in the topo
- cannot update progress with a nil diff report
- usage: VDiff -- <keyspace>.<workflow> %s [%s|<UUID>]
- invalid action '%s'; %s
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/da0692fc4e775393.
Report an issue: GitHub.