gastownhall/beads · error

search wisps (merge): probe: %w

Error message

search wisps (merge): probe: %w

What it means

In the merge path (no Ephemeral, no SkipWisps), searchAcrossIssuesAndWisps probes whether the wisps table is empty or missing via wispsTableEmptyOrMissing before deciding between an issues-only search and a UNION search. A probe error that is neither sql.ErrNoRows nor table-not-exist — connection failure, permissions, engine error — is wrapped as "search wisps (merge): probe".

Source

Thrown at internal/storage/domain/db/issue_search.go:60

		if err != nil && !missingOptionalWispTable(err) {
			return domain.SearchPage{}, fmt.Errorf("search wisps (ephemeral filter): %w", err)
		}
		if len(page.Items) > 0 {
			return page, nil
		}
	}

	if filter.SkipWisps {
		page, err := r.searchTable(ctx, query, filter, issuesFilterTables)
		if err != nil {
			return domain.SearchPage{}, fmt.Errorf("search issues: %w", err)
		}
		return page, nil
	}

	empty, probeErr := r.wispsTableEmptyOrMissing(ctx)
	if probeErr != nil {
		return domain.SearchPage{}, fmt.Errorf("search wisps (merge): probe: %w", probeErr)
	}
	if empty {
		page, err := r.searchTable(ctx, query, filter, issuesFilterTables)
		if err != nil {
			return domain.SearchPage{}, fmt.Errorf("search issues: %w", err)
		}
		return page, nil
	}

	return r.searchUnion(ctx, query, filter)
}

func (r *issueSQLRepositoryImpl) searchUnion(ctx context.Context, query string, filter types.IssueFilter) (domain.SearchPage, error) {
	outerOrderBy := unionOrderBySQL(filter.SortBy, filter.SortDesc)
	window := searchWindowForFilter(filter)
	legWindow := legWindowSQL(outerOrderBy, window)

	iSub, iArgs, err := r.buildUnionSubquery(query, filter, issuesFilterTables, "i", legWindow)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check database connectivity and Dolt server logs; run bd doctor
  2. Retry the search — the probe runs early and transient drops are the most common cause
  3. Verify the bd user has SELECT grants on the wisps table
  4. Use SkipWisps=true to skip the probe entirely if you only need durable issues

Example fix

// before: merge path always probes wisps
page, err := store.Search(ctx, q, types.IssueFilter{})
// after: skip the wisp plane when it is not needed
page, err := store.Search(ctx, q, types.IssueFilter{SkipWisps: true})
Defensive patterns

Strategy: retry

Validate before calling

if err := store.Ping(ctx); err != nil {
    return fmt.Errorf("store down, skipping search: %w", err)
}

Try / catch

page, err := store.Search(ctx, q, filter)
if err != nil && strings.Contains(err.Error(), "search wisps (merge): probe") {
    // probe failed on a real error: retry, then fall back to SkipWisps
    page, err = store.Search(ctx, q, types.IssueFilter{SkipWisps: true})
}

Prevention

When it happens

Trigger: Calling SearchAcrossIssuesAndWisps without SkipWisps when `SELECT 1 FROM wisps LIMIT 1` fails with a real error: server unreachable mid-command, denied SELECT on wisps, corrupted database file, or driver-level failure.

Common situations: Dolt server restart during a bd query; read-only user lacking grants on wisps; disk/database corruption; stale connections after a network interruption.

Related errors


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