gastownhall/beads · error
scan branch: %w
Error message
scan branch: %w
What it means
ListBranches wraps rows.Scan failure as "scan branch: <cause>" while iterating dolt_branches rows. Scan errors here mean the returned row could not be decoded into a string — unexpected NULL in the name column or a driver type mismatch. This indicates a driver/Dolt incompatibility rather than user input problems.
Source
Thrown at internal/storage/versioncontrolops/branches.go:20
import (
"context"
"fmt"
)
// ListBranches returns the names of all Dolt branches, sorted by name.
func ListBranches(ctx context.Context, db DBConn) ([]string, error) {
rows, err := db.QueryContext(ctx, "SELECT name FROM dolt_branches ORDER BY name")
if err != nil {
return nil, fmt.Errorf("list branches: %w", err)
}
defer rows.Close()
var branches []string
for rows.Next() {
var name string
if err := rows.Scan(&name); err != nil {
return nil, fmt.Errorf("scan branch: %w", err)
}
branches = append(branches, name)
}
return branches, rows.Err()
}
// CurrentBranch returns the name of the active branch.
func CurrentBranch(ctx context.Context, db DBConn) (string, error) {
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 {View on GitHub (pinned to 71377f2769)
Solutions
- Scan into sql.NullString (or *string) to tolerate NULL names
- Check the driver version matches the Dolt server version after upgrades
- Inspect the wrapped cause to identify the failing column/type
- Skip-or-fail consistently: decide whether a NULL branch name is fatal for your workflow
Example fix
// before
var name string
if err := rows.Scan(&name); err != nil { return nil, err }
// after (caller-side mitigation)
branches, err := vcops.ListBranches(ctx, db)
if err != nil {
if strings.Contains(err.Error(), "scan branch") {
return fmt.Errorf("dolt/driver mismatch: %w", err)
}
return err
} Defensive patterns
Strategy: type-guard
Type guard
func isScanErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "scan branch")
} Try / catch
branches, err := vcops.ListBranches(ctx, db)
if isScanErr(err) {
return fmt.Errorf("branch name undecodable; check driver/dolt version: %w", err)
} Prevention
- Keep SQL driver and Dolt server versions aligned
- Upgrade drivers deliberately and test dolt_branches scans after upgrades
- Never hand-edit dolt_branches storage outside Dolt
When it happens
Trigger: ListBranches when rows.Scan(&name) fails: name column NULL, driver returning a non-string type (e.g. []byte handled unexpectedly), or rows in an invalid state mid-iteration.
Common situations: Custom/alternative SQL drivers with unusual type mapping; corrupted or manually-edited dolt_branches contents; scanning with a driver version that changed result types after a Dolt upgrade.
Related errors
- failed to scan dolt_status: %w
- scan dirty config key: %w
- failed to scan diff: %w
- scan conflict row for table %s: %w
- scan dependency conflict: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/31a0d68ed644d941.
Report an issue: GitHub.