gastownhall/beads · error

db: ListRemotes: scan: %w

Error message

db: ListRemotes: scan: %w

What it means

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).

Source

Thrown at internal/storage/domain/db/remote.go:49

func (r *remoteSQLRepositoryImpl) RemoveRemote(ctx context.Context, name string) error {
	if err := r.vc.Remote(ctx, "remove", name); err != nil {
		return fmt.Errorf("db: RemoveRemote %s: %w", name, err)
	}
	return nil
}

func (r *remoteSQLRepositoryImpl) ListRemotes(ctx context.Context) ([]domain.Remote, error) {
	rows, err := r.runner.QueryContext(ctx, "SELECT name, url FROM dolt_remotes")
	if err != nil {
		return nil, fmt.Errorf("db: ListRemotes: query: %w", err)
	}
	defer rows.Close()

	var remotes []domain.Remote
	for rows.Next() {
		var rem domain.Remote
		if err := rows.Scan(&rem.Name, &rem.URL); err != nil {
			return nil, fmt.Errorf("db: ListRemotes: scan: %w", err)
		}
		remotes = append(remotes, rem)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("db: ListRemotes: rows: %w", err)
	}
	return remotes, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped cause after 'scan:' to see the exact column/type mismatch
  2. Inspect the dolt_remotes schema (SHOW CREATE TABLE) and migrate rows to match expected (name, url) string columns
  3. Fix NULL values in name/url columns (UPDATE ... SET url='') or change destinations to sql.NullString
  4. Ensure beads and the Dolt storage schema versions match

Example fix

// before
var rem domain.Remote
rows.Scan(&rem.Name, &rem.URL) // fails on NULL url
// after (library-side)
var name, url sql.NullString
rows.Scan(&name, &url)
rem = domain.Remote{Name: name.String, URL: url.String}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify expected schema before listing
var nameT, urlT string
err := db.QueryRow(`SELECT column_type FROM information_schema.columns WHERE table_name='dolt_remotes' AND column_name IN ('name','url')`).Scan(&nameT)
// or run bd doctor to validate schema drift

Type guard

func isScanErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "ListRemotes: scan:")
}

Try / catch

remotes, err := store.ListRemotes(ctx)
if err != nil && strings.Contains(err.Error(), "ListRemotes: scan:") {
    return nil, fmt.Errorf("dolt_remotes schema incompatible; run migrations: %w", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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