{"record":{"id":"31a0d68ed644d941","repo":"gastownhall/beads","slug":"scan-branch-w","errorCode":null,"errorMessage":"scan branch: %w","messagePattern":"scan branch: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/branches.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"context\"\n\t\"fmt\"\n)\n\n// ListBranches returns the names of all Dolt branches, sorted by name.\nfunc ListBranches(ctx context.Context, db DBConn) ([]string, error) {\n\trows, err := db.QueryContext(ctx, \"SELECT name FROM dolt_branches ORDER BY name\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"list branches: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tvar branches []string\n\tfor rows.Next() {\n\t\tvar name string\n\t\tif err := rows.Scan(&name); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"scan branch: %w\", err)\n\t\t}\n\t\tbranches = append(branches, name)\n\t}\n\treturn branches, rows.Err()\n}\n\n// CurrentBranch returns the name of the active branch.\nfunc CurrentBranch(ctx context.Context, db DBConn) (string, error) {\n\tvar branch string\n\tif err := db.QueryRowContext(ctx, \"SELECT active_branch()\").Scan(&branch); err != nil {\n\t\treturn \"\", fmt.Errorf(\"get current branch: %w\", err)\n\t}\n\treturn branch, nil\n}\n\n// CreateBranch creates a new Dolt branch from the current HEAD.\nfunc CreateBranch(ctx context.Context, db DBConn, name string) error {\n\tif _, err := db.ExecContext(ctx, \"CALL DOLT_BRANCH(?)\", name); err != nil {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/branches.go#L2-L38","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nvar name string\nif err := rows.Scan(&name); err != nil { return nil, err }\n// after (caller-side mitigation)\nbranches, err := vcops.ListBranches(ctx, db)\nif err != nil {\n\tif strings.Contains(err.Error(), \"scan branch\") {\n\t\treturn fmt.Errorf(\"dolt/driver mismatch: %w\", err)\n\t}\n\treturn err\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isScanErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"scan branch\")\n}","tryCatchPattern":"branches, err := vcops.ListBranches(ctx, db)\nif isScanErr(err) {\n\treturn fmt.Errorf(\"branch name undecodable; check driver/dolt version: %w\", err)\n}","preventionTips":["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"],"tags":["dolt","sql","scan","driver"],"backgroundTag":"sql-row-scan-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}