gastownhall/beads · error
db: ChildCounterSQLRepository.NextChildID: scan: %w
Error message
db: ChildCounterSQLRepository.NextChildID: scan: %w
What it means
NextChildID scans each child-issue ID returned by the query over `issues` (or `wisps`) to find the highest numeric suffix under the parent. This error wraps any database/sql rows.Scan failure while reading one ID column. It means a row could not be decoded into a Go string, which is a driver/row-decode failure rather than a missing-parent problem.
Source
Thrown at internal/storage/domain/db/child_counter.go:65
case errors.Is(err, sql.ErrNoRows):
lastChild = 0
default:
return "", fmt.Errorf("db: ChildCounterSQLRepository.NextChildID: read counter for %s: %w", parentID, err)
}
rows, err := r.runner.QueryContext(ctx, fmt.Sprintf(`
SELECT id FROM %s
WHERE id LIKE CONCAT(?, '.%%')
AND id NOT LIKE CONCAT(?, '.%%.%%')
`, issueTable), parentID, parentID) //nolint:gosec // G201: issueTable is one of two hardcoded constants
if err != nil {
return "", fmt.Errorf("db: ChildCounterSQLRepository.NextChildID: scan existing children of %s: %w", parentID, err)
}
defer rows.Close()
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
return "", fmt.Errorf("db: ChildCounterSQLRepository.NextChildID: scan: %w", err)
}
if n, ok := parseChildSuffix(id); ok && n > lastChild {
lastChild = n
}
}
if err := rows.Err(); err != nil {
return "", fmt.Errorf("db: ChildCounterSQLRepository.NextChildID: rows: %w", err)
}
next := lastChild + 1
//nolint:gosec // G201: counterTable is one of two hardcoded constants
if _, err := r.runner.ExecContext(ctx, fmt.Sprintf(`
INSERT INTO %s (parent_id, last_child) VALUES (?, ?)
ON DUPLICATE KEY UPDATE last_child = ?
`, counterTable), parentID, next, next); err != nil {
return "", fmt.Errorf("db: ChildCounterSQLRepository.NextChildID: upsert counter for %s: %w", parentID, err)
}
View on GitHub (pinned to 71377f2769)
Solutions
- Check the `issues`/`wisps` table for rows with NULL or non-text `id` values and repair them (id is expected to be a NOT NULL text primary key).
- Verify the database driver version matches what beads expects (Dolt-compatible driver); upgrade/downgrade the driver.
- Retry the call; if transient connection errors appear, check server connectivity and timeouts.
- Inspect the wrapped cause with errors.Unwrap to see the underlying driver error.
Example fix
// before: rows contain NULL id, Scan into string fails
var id string
rows.Scan(&id)
// after: tolerate NULL ids defensively (or repair the schema to NOT NULL)
var id sql.NullString
if err := rows.Scan(&id); err != nil { return "", err }
if id.Valid { /* process id.String */ } Defensive patterns
Strategy: try-catch
Validate before calling
// Go has no pre-call validation for row decoding; ensure schema integrity instead: // SELECT COUNT(*) FROM issues WHERE id IS NULL -- must be 0
Type guard
func isScanError(err error) bool {
return err != nil && strings.Contains(err.Error(), "ChildCounterSQLRepository.NextChildID: scan:")
} Try / catch
childID, err := repo.NextChildID(ctx, parentID, opts)
if err != nil {
if isScanError(err) {
// inspect/repair corrupted id row, then retry
return fmt.Errorf("corrupt child id row for %s: %w", parentID, err)
}
return err
} Prevention
- Keep `id` columns NOT NULL via schema constraints
- Never hand-edit database rows; use bd commands
- Pin the SQL driver version in go.mod
When it happens
Trigger: Calling ChildCounterSQLRepository.NextChildID(ctx, parentID, opts) when an `id` value in the result set cannot be scanned into a string (e.g. NULL id in the table, driver type conversion failure, connection dropped mid-iteration).
Common situations: Corrupted or manually edited rows where `issues.id` is NULL; driver mismatch after switching Dolt/MySQL driver versions with stricter Scan conversion; network interruption while iterating rows.
Related errors
- db: CommentSQLRepository.CountsByIssueIDs: scan: %w
- db: CommentSQLRepository.ListByIssueIDs: scan: %w
- db: LabelSQLRepository.List: scan: %w
- db: LabelSQLRepository.ListByIssueIDs: scan: %w
- get issues by IDs: scan: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/9565bf3e540dc240.
Report an issue: GitHub.