gastownhall/beads · warning

delete branch

Error message

delete branch %s: %w

What it means

DeleteBranch runs CALL DOLT_BRANCH('-D', ?) to force-delete a branch and wraps failures as 'delete branch <name>: %w'. Dolt errors when the branch does not exist or cannot be deleted (e.g. it is the current branch). The wrapped driver error preserves Dolt's specific message.

Solutions

  1. Treat 'branch not found' from the wrapped error as success (idempotent delete) rather than a failure
  2. Checkout another branch (e.g. main) before deleting the current branch
  3. Verify the branch exists with a dolt_branches query before deleting

Example fix

// before
err := versioncontrolops.DeleteBranch(ctx, db, "compact-tmp")
// after
err := versioncontrolops.DeleteBranch(ctx, db, "compact-tmp")
if err != nil && !strings.Contains(err.Error(), "not found") {
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

var count int
_ = db.QueryRowContext(ctx,
    "SELECT COUNT(*) FROM dolt_branches WHERE name = ?", name).Scan(&count)
// count == 0 → already deleted, skip

Try / catch

err := versioncontrolops.DeleteBranch(ctx, db, name)
if err != nil {
    if strings.Contains(err.Error(), "not found") || strings.Contains(err.Error(), "unknown branch") {
        return nil // idempotent delete
    }
    return err
}

Prevention

When it happens

Trigger: Calling DeleteBranch on a branch name that doesn't exist; attempting to delete the currently checked-out branch; the delete call failing due to connection problems.

Common situations: Best-effort cleanup code deleting an already-deleted temp branch (e.g. compact-tmp deleted twice); trying to delete 'main' while checked out on it; typo in branch name.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/58ef210e75d9ebf1. Report an issue: GitHub.

Appendix: source

Thrown at internal/storage/versioncontrolops/branches.go:47

	var branch string
	if err := db.QueryRowContext(ctx, "SELECT active_branch()").Scan(&branch); err != nil {
		return "", fmt.Errorf("get current branch: %w", err)
	}
	return branch, nil
}

// CreateBranch creates a new Dolt branch from the current HEAD.
func CreateBranch(ctx context.Context, db DBConn, name string) error {
	if _, err := db.ExecContext(ctx, "CALL DOLT_BRANCH(?)", name); err != nil {
		return fmt.Errorf("create branch %s: %w", name, err)
	}
	return nil
}

// DeleteBranch force-deletes a Dolt branch.
func DeleteBranch(ctx context.Context, db DBConn, name string) error {
	if _, err := db.ExecContext(ctx, "CALL DOLT_BRANCH('-D', ?)", name); err != nil {
		return fmt.Errorf("delete branch %s: %w", name, err)
	}
	return nil
}

// CheckoutBranch switches the active session to the named branch.
func CheckoutBranch(ctx context.Context, db DBConn, name string) error {
	if _, err := db.ExecContext(ctx, "CALL DOLT_CHECKOUT(?)", name); err != nil {
		return fmt.Errorf("checkout branch %s: %w", name, err)
	}
	return nil
}

View on GitHub (pinned to 71377f2769)