vitessio/vitess · error

failed to delete tablet: %w

Error message

failed to delete tablet: %w

What it means

VTAdmin's DeleteTablet RPC wraps the underlying cluster error when the vtctld DeleteTablets call fails, producing 'failed to delete tablet: <cause>'. The authorization and tablet lookup succeeded; the failure happened in the vtctld/toposerver layer while removing the tablet record. The cause (after the %w wrap) identifies the actual problem.

Source

Thrown at go/vt/vtadmin/api.go:697

	return c.DeleteShards(ctx, req.Options)
}

// DeleteTablet is part of the vtadminpb.VTAdminServer interface.
func (api *API) DeleteTablet(ctx context.Context, req *vtadminpb.DeleteTabletRequest) (*vtadminpb.DeleteTabletResponse, error) {
	span, ctx := trace.NewSpan(ctx, "API.DeleteTablet")
	defer span.Finish()

	tablet, c, err := api.getTabletForAction(ctx, span, rbac.DeleteAction, req.Alias, req.ClusterIds)
	if err != nil {
		return nil, err
	}

	if _, err := c.DeleteTablets(ctx, &vtctldatapb.DeleteTabletsRequest{
		AllowPrimary:  req.AllowPrimary,
		TabletAliases: []*topodatapb.TabletAlias{tablet.Tablet.Alias},
	}); err != nil {
		return nil, fmt.Errorf("failed to delete tablet: %w", err)
	}

	return &vtadminpb.DeleteTabletResponse{
		Status:  "ok",
		Cluster: c.ToProto(),
	}, nil
}

// EmergencyFailoverShard is part of the vtadminpb.VTAdminServer interface.
func (api *API) EmergencyFailoverShard(ctx context.Context, req *vtadminpb.EmergencyFailoverShardRequest) (*vtadminpb.EmergencyFailoverShardResponse, error) {
	span, ctx := trace.NewSpan(ctx, "API.EmergencyFailoverShard")
	defer span.Finish()

	c, err := api.getClusterForRequest(req.ClusterId)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. If deleting a primary, retry with allow_primary=true in the request (after confirming replication is healthy)
  2. Check the wrapped cause: run the equivalent vtctldclient DeleteTablets command to see the detailed vtctld error
  3. Verify vtadmin can reach the cluster's vtctld and that the topo (etcd/zk) is healthy
  4. Refresh the tablet list; if the tablet is already gone, treat the delete as a no-op

Example fix

// before: fails deleting a primary
DELETE /api/tablet/zone1-0000000100
// after
DELETE /api/tablet/zone1-0000000100?allow_primary=true
Defensive patterns

Strategy: try-catch

Validate before calling

const tablet = await getTablet(alias);
if (tablet.tablet.type === 'PRIMARY' && !allowPrimary) {
  throw new Error('refusing to delete serving primary ' + alias + ' without allow_primary');
}
if (!(await topoHasTablet(clusterId, alias))) {
  console.warn('tablet ' + alias + ' not in topo; delete is a no-op');
}

Type guard

function isTabletDeleteFailure(err: unknown): boolean {
  return err instanceof Error && err.message.startsWith('failed to delete tablet:');
}

Try / catch

try {
  await deleteTablet(clusterId, alias, { allowPrimary });
} catch (err) {
  const cause = String(err).replace('failed to delete tablet: ', '');
  if (cause.includes('is a primary')) {
    await deleteTablet(clusterId, alias, { allowPrimary: true });
  } else if (cause.includes('already deleted') || cause.includes('not found')) {
    return; // treat as success
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling DeleteTablet (DELETE /tablet) where the underlying c.DeleteTablets vtctld call errors — e.g. the tablet is still a serving primary and AllowPrimary is false, the tablet record is locked/updated concurrently, vtctld is unreachable, or the tablet alias no longer exists in the topo.

Common situations: Trying to delete a serving primary without allow_primary=true; topology inconsistencies after an aborted vtctld operation; network/partition between vtadmin and vtctld; stale vtadmin cache showing a tablet that was already deleted.

Related errors


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