vitessio/vitess · error

no vdiff table found for %s on tablet %v

Error message

no vdiff table found for %s on tablet %v

What it means

When starting the diff, for each table in the plan vdiff queries the _vt.vdiff_table rows for this vdiff id. If no row exists for a table that is in the tableDiffers map, the internal state is inconsistent and this error is thrown before any diffing starts.

Source

Thrown at go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go:403

		case <-ctx.Done():
			return vterrors.Errorf(vtrpcpb.Code_CANCELED, "context has expired")
		case <-wd.ct.done:
			return ErrVDiffStoppedByUser
		default:
		}
		query, err := sqlparser.ParseAndBind(sqlGetVDiffTable,
			sqltypes.Int64BindVariable(wd.ct.id),
			sqltypes.StringBindVariable(td.table.Name),
		)
		if err != nil {
			return err
		}
		qr, err := dbClient.ExecuteFetch(query, 1)
		if err != nil {
			return err
		}
		if len(qr.Rows) == 0 {
			return fmt.Errorf("no vdiff table found for %s on tablet %v",
				td.table.Name, wd.ct.vde.thisTablet.Alias)
		}

		log.Info(fmt.Sprintf("Starting diff of table %s for vdiff %s", td.table.Name, wd.ct.uuid))
		if err := wd.diffTable(ctx, dbClient, td); err != nil {
			return wd.markTableErrored(ctx, dbClient, td, err)
		}
		if err := td.updateTableState(ctx, dbClient, CompletedState); err != nil {
			return err
		}
		log.Info(fmt.Sprintf("Completed diff of table %s for vdiff %s", td.table.Name, wd.ct.uuid))
	}
	if err := wd.markIfCompleted(ctx, dbClient); err != nil {
		return err
	}
	return nil
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Cancel the vdiff and start a fresh one (`CancelVExec`/`vd ct cancel` then re-run vdiff) so table rows are re-created
  2. Inspect `_vt.vdiff_table` on the target primary for the vdiff id and confirm which rows are missing
  3. Avoid manual deletes on _vt tables; if rows were removed, recreate the workflow's vdiff from scratch
  4. Ensure vtctld and tablets are on compatible Vitess versions during the vdiff

Example fix

// vtctlclient
vtctldclient VDiff -- tabletspec ... cancel <keyspace> <workflow>
vtctldclient VDiff -- ... show <keyspace> <workflow>  # then re-run vdiff
Defensive patterns

Strategy: retry

Validate before calling

// check per-table state exists before resuming
qr, _ := dbClient.ExecuteFetch(fmt.Sprintf(
  "SELECT 1 FROM _vt.vdiff_table WHERE vdiff_id=%d AND table_name='%s'", id, table), 1)
if len(qr.Rows) == 0 { // state missing: cancel and restart vdiff instead of resuming }

Type guard

null

Try / catch

if err := wd.diff(ctx, dbClient); err != nil {
  if strings.Contains(err.Error(), "no vdiff table found for") {
    // cancel and start a fresh vdiff to rebuild per-table state
    _ = wd.cancel(ctx)
    return startFreshVDiff(ctx)
  }
  return err
}

Prevention

When it happens

Trigger: A vdiff run whose expected per-table row in _vt.vdiff_table is missing on this tablet — e.g. the vdiff record was partially created, rows were deleted/cleaned concurrently, or the diff is being resumed against a tablet whose local vdiff state was wiped.

Common situations: Interruption during vdiff creation (vtctld crash between inserting the vdiff row and its table rows); manual cleanup of _vt.vdiff_table rows; running vdiff on a different target tablet than where state was created; upgrading Vitess mid-vdiff.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/b4f9f2904d6c8bdb. Report an issue: GitHub.