gastownhall/beads · error
wisp id set: scan: %w
Error message
wisp id set: scan: %w
What it means
Thrown when rows.Scan fails decoding an id column from the wisp batch SELECT into a string. Like the deferred-wake scan error, this indicates a row whose id cannot be converted — NULL id, incompatible driver type, or corrupted row. Rows are closed before returning to release the cursor.
Source
Thrown at internal/storage/issueops/wisp_routing.go:98
end = len(ids)
}
batch := ids[start:end]
placeholders := make([]string, len(batch))
args := make([]any, len(batch))
for i, id := range batch {
placeholders[i] = "?"
args[i] = id
}
q := fmt.Sprintf("SELECT id FROM wisps WHERE id IN (%s)", strings.Join(placeholders, ","))
rows, err := tx.QueryContext(ctx, q, args...)
if err != nil {
return nil, fmt.Errorf("wisp id set: %w", err)
}
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
_ = rows.Close()
return nil, fmt.Errorf("wisp id set: scan: %w", err)
}
set[id] = struct{}{}
}
_ = rows.Close()
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("wisp id set: rows: %w", err)
}
}
return set, nil
}
// partitionByWispSet splits ids into (wispIDs, permIDs) using the provided
// wisp-id set. If wispSet is nil the caller must populate it first via
// WispIDSetInTx; this helper does no I/O.
func partitionByWispSet(ids []string, wispSet map[string]struct{}) (wispIDs, permIDs []string) {
for _, id := range ids {
if _, isWisp := wispSet[id]; isWisp {
wispIDs = append(wispIDs, id)View on GitHub (pinned to 71377f2769)
Solutions
- Find and fix the row with the malformed id in the wisps table.
- Enforce id VARCHAR NOT NULL PRIMARY KEY on the wisps table.
- Update the driver if the id column type/charset conversion is mishandled.
- Run storage integrity checks to detect further corruption.
Example fix
// before id VARCHAR(255) NULL // after id VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL PRIMARY KEY
Defensive patterns
Strategy: validation
Validate before calling
rows, err := db.Query("SELECT id FROM wisps WHERE id IS NULL")
if err != nil { return err }
defer rows.Close()
if rows.Next() { return errors.New("wisps rows with NULL id found: repair table before routing") } Try / catch
if err != nil {
if strings.Contains(err.Error(), "converting NULL to string") {
return fmt.Errorf("corrupt wisps row (NULL id): repair wisps table")
}
return err
} Prevention
- Keep wisps.id NOT NULL PRIMARY KEY.
- Insert wisps rows only through beads APIs, never by hand.
- Use a current driver with proper charset/type handling for id columns.
- Schedule periodic integrity checks on the wisps table.
When it happens
Trigger: Calling WispIDSetInTx when a row in wisps has a NULL or non-string id, or the driver mis-declares the id column type/charset so Scan cannot convert it.
Common situations: Manually inserted rows with NULL id; Dolt/MySQL driver charset mismatches on the id column; binary-typed id columns after schema tampering.
Related errors
- partition wisp ids: scan: %w
- get dependency records: scan: %w
- wake expired defers: scan %s row: %w
- wisp id set: probe: %w
- wisp id set: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/12050cd291af5952.
Report an issue: GitHub.