gastownhall/beads · error

query wisp dependents: %w

Error message

query wisp dependents: %w

What it means

This error wraps a failure of the batched query `SELECT issue_id FROM wisp_dependencies WHERE <target> IN (...)` used during the recursive dependent traversal. The query failed at the driver level, so the traversal stops and returns whatever was already discovered alongside the error.

Source

Thrown at internal/storage/issueops/bulk_ops.go:389

	for len(toProcess) > 0 {
		if len(seen) > maxResults {
			return discovered, fmt.Errorf("wisp cascade traversal discovered over %d issues; aborting", maxResults)
		}

		end := batchSize
		if end > len(toProcess) {
			end = len(toProcess)
		}
		batch := toProcess[:end]
		toProcess = toProcess[end:]

		placeholders, args := buildSQLInClause(batch)
		rows, err := tx.QueryContext(ctx,
			fmt.Sprintf(`SELECT issue_id FROM wisp_dependencies WHERE %s IN (%s)`, DepTargetExpr, placeholders),
			args...)
		if err != nil {
			return discovered, fmt.Errorf("query wisp dependents: %w", err)
		}

		for rows.Next() {
			var depID string
			if err := rows.Scan(&depID); err != nil {
				_ = rows.Close()
				return discovered, fmt.Errorf("scan wisp dependent: %w", err)
			}
			if !seen[depID] {
				seen[depID] = true
				discovered[depID] = true
				toProcess = append(toProcess, depID)
			}
		}
		_ = rows.Close()
		if err := rows.Err(); err != nil {
			return discovered, fmt.Errorf("iterate wisp dependents: %w", err)
		}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry the traversal; the discovered set returned with the error can seed a resume.
  2. Check the wrapped driver error — if it's a lock timeout, reduce concurrent writes to wisp_dependencies.
  3. Verify the wisp_dependencies schema/DepTargetExpr column exists after upgrades.
  4. Reduce batch size if the driver reports a placeholder/parameter limit.

Example fix

// before
ids, err := store.FindWispDependentsRecursive(ctx, tx, rootID, max) // transient connection drop
// after
var ids map[string]bool
for attempt := 0; attempt < 3; attempt++ {
    ids, err = store.FindWispDependentsRecursive(ctx, tx, rootID, max)
    if err == nil { break }
    time.Sleep(time.Second * time.Duration(attempt+1))
}
Defensive patterns

Strategy: retry

Validate before calling

if err := store.Ping(ctx); err != nil {
    return fmt.Errorf("storage unreachable; skip traversal: %w", err)
}

Try / catch

var lastErr error
for attempt := 0; attempt < 3; attempt++ {
    ids, err := store.FindWispDependentsRecursive(ctx, tx, rootID, max)
    if err == nil { return ids, nil }
    lastErr = err
    if !strings.Contains(err.Error(), "query wisp dependents:") { return nil, err }
    time.Sleep(time.Second << attempt)
}
return nil, lastErr

Prevention

When it happens

Trigger: Calling FindWispDependentsRecursiveInTx when a batch SELECT fails: connection drop, lock contention on wisp_dependencies, too-many-parameters from an oversized batch, or schema mismatch on DepTargetExpr's underlying column.

Common situations: Flaky network to the Dolt server mid-traversal; concurrent writes locking wisp_dependencies; version skew where the code expects a column the table doesn't have; batch size exceeding driver placeholder limits.

Related errors


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