googleapis/mcp-toolbox · error

failed to delete instance

Error message

failed to delete instance: %w

What it means

This error is a wrapper raised by the Bigtable source's DeleteInstance method when the underlying InstanceAdmin.DeleteInstance call to the Cloud Bigtable Admin API fails. The original gRPC/googleapi error is preserved via %w, so callers can unwrap it with errors.As/Is to inspect codes like NotFound or PermissionDenied. It simply means the admin API rejected or failed the delete request for the given instance.

Solutions

  1. Verify the instance ID exists first with ListInstances or `gcloud bigtable instances list`.
  2. Check IAM: grant the caller the roles/bigtable.admin (or bigtable.instances.delete) role on the project.
  3. Confirm the correct project is configured (BIGTABLE_PROJECT_ID / client project option).
  4. Unwrap the error with errors.As(*googleapi.Error) or status.FromError and branch on its code; retry only on transient codes (Unavailable, DeadlineExceeded).

Example fix

// before
if err != nil {
    return nil, fmt.Errorf("failed to delete instance: %w", err)
}
// after
if err != nil {
    if st, ok := status.FromError(err); ok && st.Code() == codes.NotFound {
        return map[string]string{"status": "instance already deleted"}, nil
    }
    return nil, fmt.Errorf("failed to delete instance: %w", err)
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before calling DeleteInstance
instances, _ := src.ListInstances(ctx)
for _, in := range instances.([]*bigtable.Instance) {
    if in.Name == instanceId {
        exists = true
    }
}
if !exists {
    return // skip delete; instance already gone
}

Type guard

func isNotFound(err error) bool {
    var ge *googleapi.Error
    if errors.As(err, &ge) {
        return ge.Code == 404
    }
    if st, ok := status.FromError(errors.Unwrap(err)); ok {
        return st.Code() == codes.NotFound
    }
    return false
}

Try / catch

if _, err := src.DeleteInstance(ctx, id); err != nil {
    var wrapped *fmt.WrapError // or just unwrap generically
    if isNotFound(err) {
        log.Printf("instance %s already deleted", id)
        return
    }
    return fmt.Errorf("delete instance %s: %w", id, err)
}

Prevention

When it happens

Trigger: Calling DeleteInstance(ctx, instanceId) when the instance does not exist (NotFound), the credentials/service account lack bigtable.instances.delete IAM permission (PermissionDenied), the instance is already being deleted, or transient gRPC/network failures interrupt the admin RPC.

Common situations: Typos or stale instance IDs after an instance was removed out-of-band; running with Application Default Credentials from an account missing the Bigtable Admin role; attempting deletion in the wrong project (misconfigured project env var); duplicate delete attempts in automation scripts.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/9a7a5ef47fd227ae. Report an issue: GitHub.

Appendix: source

Thrown at internal/sources/bigtable/admin_wrappers.go:64

	return map[string]string{"status": "instance created successfully"}, nil
}

func (s *Source) UpdateInstance(ctx context.Context, instanceId, displayName string) (any, error) {
	conf := &bigtable.InstanceWithClustersConfig{
		InstanceID:  instanceId,
		DisplayName: displayName,
	}
	err := s.InstanceAdmin.UpdateInstanceWithClusters(ctx, conf)
	if err != nil {
		return nil, fmt.Errorf("failed to update instance: %w", err)
	}
	return map[string]string{"status": "instance updated successfully"}, nil
}

func (s *Source) DeleteInstance(ctx context.Context, instanceId string) (any, error) {
	err := s.InstanceAdmin.DeleteInstance(ctx, instanceId)
	if err != nil {
		return nil, fmt.Errorf("failed to delete instance: %w", err)
	}
	return map[string]string{"status": "instance deleted successfully"}, nil
}

func (s *Source) ListInstances(ctx context.Context) (any, error) {
	instances, err := s.InstanceAdmin.Instances(ctx)
	if err != nil {
		var partialErr bigtable.ErrPartiallyUnavailable
		if errors.As(err, &partialErr) {
			return instances, nil
		}
		return nil, fmt.Errorf("failed to list instances: %w", err)
	}
	return instances, nil
}

func (s *Source) GetCluster(ctx context.Context, instanceId, clusterId string) (any, error) {
	cluster, err := s.InstanceAdmin.GetCluster(ctx, instanceId, clusterId)

View on GitHub (pinned to 8cc6e09de2)