{"record":{"id":"7d0d8bf7571213be","repo":"gastownhall/beads","slug":"db-listremotes-scan-w","errorCode":null,"errorMessage":"db: ListRemotes: scan: %w","messagePattern":"db: ListRemotes: scan: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/remote.go","lineNumber":49,"sourceCode":"func (r *remoteSQLRepositoryImpl) RemoveRemote(ctx context.Context, name string) error {\n\tif err := r.vc.Remote(ctx, \"remove\", name); err != nil {\n\t\treturn fmt.Errorf(\"db: RemoveRemote %s: %w\", name, err)\n\t}\n\treturn nil\n}\n\nfunc (r *remoteSQLRepositoryImpl) ListRemotes(ctx context.Context) ([]domain.Remote, error) {\n\trows, err := r.runner.QueryContext(ctx, \"SELECT name, url FROM dolt_remotes\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"db: ListRemotes: query: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tvar remotes []domain.Remote\n\tfor rows.Next() {\n\t\tvar rem domain.Remote\n\t\tif err := rows.Scan(&rem.Name, &rem.URL); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"db: ListRemotes: scan: %w\", err)\n\t\t}\n\t\tremotes = append(remotes, rem)\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"db: ListRemotes: rows: %w\", err)\n\t}\n\treturn remotes, nil\n}\n","sourceCodeStart":31,"sourceCodeEnd":58,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/remote.go#L31-L58","documentation":"This error occurs while scanning a row of the dolt_remotes result set into a domain.Remote struct during ListRemotes. rows.Scan returned an error, typically a column/type mismatch between the query output and the destination fields (&rem.Name, &rem.URL).","triggerScenarios":"Calling ListRemotes when the dolt_remotes table's columns cannot be scanned into (string, string): schema drift where name/url columns changed type, NULL values in non-pointer string destinations, or driver returning unexpected column types.","commonSituations":"Database created by a different beads/Dolt version whose dolt_remotes schema differs; NULL url for a manually inserted remote; corrupted rows after a partial migration.","solutions":["Read the wrapped cause after 'scan:' to see the exact column/type mismatch","Inspect the dolt_remotes schema (SHOW CREATE TABLE) and migrate rows to match expected (name, url) string columns","Fix NULL values in name/url columns (UPDATE ... SET url='') or change destinations to sql.NullString","Ensure beads and the Dolt storage schema versions match"],"exampleFix":"// before\nvar rem domain.Remote\nrows.Scan(&rem.Name, &rem.URL) // fails on NULL url\n// after (library-side)\nvar name, url sql.NullString\nrows.Scan(&name, &url)\nrem = domain.Remote{Name: name.String, URL: url.String}","handlingStrategy":"try-catch","validationCode":"// verify expected schema before listing\nvar nameT, urlT string\nerr := db.QueryRow(`SELECT column_type FROM information_schema.columns WHERE table_name='dolt_remotes' AND column_name IN ('name','url')`).Scan(&nameT)\n// or run bd doctor to validate schema drift","typeGuard":"func isScanErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"ListRemotes: scan:\")\n}","tryCatchPattern":"remotes, err := store.ListRemotes(ctx)\nif err != nil && strings.Contains(err.Error(), \"ListRemotes: scan:\") {\n    return nil, fmt.Errorf(\"dolt_remotes schema incompatible; run migrations: %w\", err)\n}","preventionTips":["Keep beads and Dolt schema versions in sync","Avoid hand-editing dolt_remotes rows (no NULLs in name/url)","Run bd doctor after upgrades to catch schema drift"],"tags":["database","sql","scan","schema"],"backgroundTag":"sql-row-scan-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}