gastownhall/beads · error

partition wisp ids: scan: %w

Error message

partition wisp ids: scan: %w

What it means

During PartitionWispIDsInTx row iteration, rows.Scan into a single string ID failed. This wraps the sql.Rows.Scan error — typically a type/conversion mismatch or a driver-level row error surfaced at scan time. The partial wispSet is discarded so callers never see an untrustworthy partition.

Source

Thrown at internal/storage/issueops/wisp_routing.go:170

			placeholders[i] = "?"
			args[i] = id
		}
		//nolint:gosec // G201: only ? placeholders in the IN clause.
		rows, qErr := tx.QueryContext(ctx,
			fmt.Sprintf("SELECT id FROM wisps WHERE id IN (%s)", strings.Join(placeholders, ",")),
			args...)
		if qErr != nil {
			// Wisps table may not exist yet on older schemas — treat as "no wisps".
			if isTableNotExistError(qErr) {
				return nil, append([]string(nil), ids...), nil
			}
			return nil, nil, fmt.Errorf("partition wisp ids: %w", qErr)
		}
		for rows.Next() {
			var id string
			if scanErr := rows.Scan(&id); scanErr != nil {
				_ = rows.Close()
				return nil, nil, fmt.Errorf("partition wisp ids: scan: %w", scanErr)
			}
			wispSet[id] = struct{}{}
		}
		_ = rows.Close()
		if rowsErr := rows.Err(); rowsErr != nil {
			return nil, nil, fmt.Errorf("partition wisp ids: rows: %w", rowsErr)
		}
	}

	for _, id := range ids {
		if _, ok := wispSet[id]; ok {
			wispIDs = append(wispIDs, id)
		} else {
			permIDs = append(permIDs, id)
		}
	}
	return wispIDs, permIDs, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped scan error for sql.ErrNoRows vs conversion errors; verify the wisps.id column type matches expectations
  2. Re-run migrations so the schema matches what this code expects (id as string)
  3. Retry with a fresh connection/transaction if the cause was a dropped connection
  4. Ensure the context is not cancelled prematurely by the caller (check parent deadlines)

Example fix

// before
rows, err := tx.QueryContext(ctx, q, args...)
// ... Scan fails with conversion error after schema drift
// after
// 1. run migrations: bd migrate (or equivalent) to restore wisps.id type
// 2. retry the partition on a fresh tx
wispIDs, permIDs, err := issueops.PartitionWispIDsInTx(freshCtx, freshTx, ids)
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure schema matches expectations before partitioning
_ = store.RunMigrations(ctx) // keeps wisps.id column type as expected

Try / catch

wispIDs, permIDs, err := issueops.PartitionWispIDsInTx(ctx, tx, ids)
if err != nil {
	var scanErr *fmt.ScanError // or inspect wrapped driver error
	if strings.Contains(err.Error(), "scan") {
		// schema drift suspected: run migrations, then retry
	}
	return err
}

Prevention

When it happens

Trigger: Calling PartitionWispIDsInTx (or its wrappers: GetCommentsForIssuesInTx, GetCommentCountsInTx, ResolveDeletionSetInTx, GetDependencyRecordsForIssuesInTx, GetBlockingInfoForIssuesInTx, GetLabelsForIssuesInTx) when a row in the wisps result set cannot be scanned into a string — e.g. the id column type changed, the connection broke mid-iteration, or the context was cancelled between Next() and Scan().

Common situations: Schema drift where wisps.id is no longer a plain string/varchar; connection killed mid-result-stream by a proxy or Dolt server restart; context cancellation racing row iteration.

Related errors


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