gastownhall/beads · error

wisp id set: %w

Error message

wisp id set: %w

What it means

Thrown when the batched SELECT id FROM wisps WHERE id IN (...) fails to execute. After confirming the wisps table is non-empty, WispIDSetInTx queries ids in batches of queryBatchSize; any driver, connection, or SQL error in that query is wrapped here. The result determines which of the caller's ids are routed as wisps.

Source

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

	} else if empty {
		return set, nil
	}
	for start := 0; start < len(ids); start += queryBatchSize {
		end := start + queryBatchSize
		if end > len(ids) {
			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

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped driver error for connection vs missing-table vs syntax causes.
  2. Run migrations to recreate the wisps table if it is missing.
  3. Retry the operation once the database connection is healthy.
  4. Check server logs if the batch query was killed for resource limits.

Example fix

// before: wisps table dropped
DROP TABLE wisps;
// after: recreate via migration
CREATE TABLE wisps (id VARCHAR(255) NOT NULL PRIMARY KEY, ...);
Defensive patterns

Strategy: retry

Validate before calling

var exists string
if err := db.QueryRow("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME='wisps'").Scan(&exists); err != nil {
    return errors.New("wisps table missing: run beads migration")
}

Try / catch

err := retry.Do(func() error {
    _, err := issueops.GetIssuesByIDsInTx(ctx, tx, ids)
    return err
}, retry.Attempts(3), retry.Delay(500*time.Millisecond))

Prevention

When it happens

Trigger: Calling DeleteInTx, GetIssuesByIDsInTx, ExecuteAddDependencies, or ReconcileChildCounters with ids present in the codebase while the wisps SELECT fails: broken connection, wisps table dropped mid-operation, or SQL error from a malformed batch.

Common situations: Schema migration removed/renamed the wisps table while old code still runs; connection dropped during a mixed write/read transaction; server killed the IN-query for resource reasons.

Related errors


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