gastownhall/beads · error

partition wisp ids: probe: %w

Error message

partition wisp ids: probe: %w

What it means

PartitionWispIDsInTx first probes whether the wisps table is empty or missing (SELECT 1 FROM wisps LIMIT 1). This error wraps a probe failure that is neither sql.ErrNoRows nor a table-not-exist error — i.e. a genuine query failure such as a connection error, permission denial, or corrupt table. The partition cannot proceed because wisp status is unknown.

Source

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

		}
	}
	return wispIDs, permIDs
}

// PartitionWispIDsInTx partitions a set of IDs into wisp vs non-wisp buckets
// using a single batched `SELECT id FROM wisps WHERE id IN (...)` query per
// queryBatchSize chunk, rather than one round-trip per ID. This is critical
// for remote backends (Dolt) where per-ID round-trips multiply WAN latency
// and can push bulk hydration past the context deadline (see GH#3414).
// IDs not present in the wisps table are treated as permanent issue IDs.
// Returned slices preserve the input ordering within each bucket.
func PartitionWispIDsInTx(ctx context.Context, tx DBTX, ids []string) (wispIDs, permIDs []string, err error) {
	if len(ids) == 0 {
		return nil, nil, nil
	}

	if empty, probeErr := wispsTableEmptyOrMissingInTx(ctx, tx); probeErr != nil {
		return nil, nil, fmt.Errorf("partition wisp ids: probe: %w", probeErr)
	} else if empty {
		return nil, append([]string(nil), ids...), nil
	}

	wispSet := make(map[string]struct{}, len(ids))
	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
		}
		//nolint:gosec // G201: only ? placeholders in the IN clause.

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error — fix the underlying connectivity or permission problem first
  2. Confirm the DB user/role has SELECT on the wisps table
  3. For remote Dolt, verify the server is up and reachable (network, port, TLS) before retrying
  4. If the wisps table is corrupt or the schema is mid-migration, run schema repair/migrations to a consistent version
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure store is healthy before batch operations
if err := store.Ping(ctx); err != nil { return fmt.Errorf("store unavailable: %w", err) }

Try / catch

wispIDs, permIDs, err := issueops.PartitionWispIDsInTx(ctx, tx, ids)
if err != nil {
	if strings.Contains(err.Error(), "partition wisp ids: probe:") {
		// fall back: treat all as permanent after verifying connectivity
	}
	return err
}

Prevention

When it happens

Trigger: Calling PartitionWispIDsInTx (directly or via GetCommentsForIssuesInTx, GetCommentCountsInTx, ResolveDeletionSetInTx, GetDependencyRecordsForIssuesInTx, GetBlockingInfoForIssuesInTx, GetLabelsForIssuesInTx) when the probe SELECT against wisps fails with a non-table-not-exist driver error (dead connection, access denied, locked DB).

Common situations: Dolt server unreachable at call time; the DB user lacks SELECT permission on the wisps table; database file locked by another process in embedded mode; transient network failure against a remote Dolt backend.

Related errors


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