googleapis/mcp-toolbox · error

failed to delete table: %w

Error message

failed to delete table: %w

What it means

This error wraps failures from the Bigtable Admin client's DeleteTable call in Source.DeleteTable. The library wraps the underlying error with fmt.Errorf("failed to delete table: %w", err) while preserving the original gRPC cause (not found, permissions, network) in the wrapped chain.

Source

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

}

func (s *Source) CreateTable(ctx context.Context, tableId, columnFamily string) (any, error) {
	err := s.Admin.CreateTable(ctx, tableId)
	if err != nil {
		return nil, fmt.Errorf("failed to create table: %w", err)
	}
	if columnFamily != "" {
		if err := s.Admin.CreateColumnFamily(ctx, tableId, columnFamily); err != nil {
			return nil, fmt.Errorf("failed to create column family: %w", err)
		}
	}
	return map[string]string{"status": "table created successfully"}, nil
}

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

func (s *Source) ListTables(ctx context.Context) (any, error) {
	tables, err := s.Admin.Tables(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to list tables: %w", err)
	}
	return tables, nil
}

func (s *Source) UpdateTable(ctx context.Context, tableId string, disableChangeStream bool) (any, error) {
	var err error
	if disableChangeStream {
		err = s.Admin.UpdateTableDisableChangeStream(ctx, tableId)
	} else {
		err = s.Admin.UpdateTableWithChangeStream(ctx, tableId, 24*time.Hour)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Confirm tableId exists via list_tables; treat gRPC NotFound as already deleted for idempotency.
  2. Check IAM: caller needs roles/bigtable.admin (or bigtable.tables.delete).
  3. Remove or account for backups/authorized views that pin the table, then retry.
  4. Retry transient gRPC errors (Unavailable/DeadlineExceeded) with exponential backoff.

Example fix

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

Strategy: try-catch

Validate before calling

// Go: confirm the table exists before delete
tables, err := admin.Tables(ctx)
if err == nil && !slices.Contains(tables, tableId) {
    return nil // already deleted
}

Type guard

func isTableGone(err error) bool {
    return status.Code(err) == codes.NotFound
}

Try / catch

if err := src.DeleteTable(ctx, tableId); err != nil {
    if status.Code(err) == codes.NotFound {
        return nil // idempotent success
    }
    return fmt.Errorf("delete table: %w", err)
}

Prevention

When it happens

Trigger: Calling the bigtable delete_table tool where s.Admin.DeleteTable(ctx, tableId) errors: tableId does not exist, caller lacks bigtable.tables.delete IAM permission, the table is protected by an active backup/authorization, or a transient gRPC failure occurs.

Common situations: Deleting an already-deleted table in idempotent cleanup scripts; typos in table IDs; service account with viewer-only rights; delete blocked because the table is in a backup schedule or logical view in some setups.

Related errors


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