gastownhall/beads · error

descendants: wisps table probe: %w

Error message

descendants: wisps table probe: %w

What it means

GetDescendants wraps a failure from wispsTableEmptyOrMissing, the probe that decides whether the recursive CTE should include a wisps branch. The probe runs `SELECT 1 FROM wisps LIMIT 1`; any error that is neither sql.ErrNoRows nor a table-not-exist error (e.g. connection loss, engine failure, permissions) is wrapped as "descendants: wisps table probe". It signals the store could not even determine whether the ephemeral wisp plane exists, not a data problem.

Source

Thrown at internal/storage/domain/db/issue_descendants.go:57

	levelFilter := filter
	levelFilter.ParentID = nil
	levelFilter.Limit = 0
	levelFilter.Offset = 0

	issueWhereClauses, issueArgs, err := buildIssueFilterClauses("", levelFilter, issuesFilterTables)
	if err != nil {
		return nil, fmt.Errorf("descendants: issues filter: %w", err)
	}

	wispDepsExist, err := r.optionalTableExists(ctx, "wisp_dependencies")
	if err != nil {
		return nil, fmt.Errorf("descendants: wisp_dependencies probe: %w", err)
	}
	walkWisps := wispDepsExist && !filter.SkipWisps
	if walkWisps {
		empty, probeErr := r.wispsTableEmptyOrMissing(ctx)
		if probeErr != nil {
			return nil, fmt.Errorf("descendants: wisps table probe: %w", probeErr)
		}
		walkWisps = !empty
	}

	var wispWhereClauses []string
	var wispArgs []any
	if walkWisps {
		wispWhereClauses, wispArgs, err = buildIssueFilterClauses("", levelFilter, wispsFilterTables)
		if err != nil {
			return nil, fmt.Errorf("descendants: wisps filter: %w", err)
		}
	}

	issuePred := buildDescendantsPred("issues", "i", "issue_matches", issueWhereClauses, issueArgs)
	var wispPred predBundle
	if walkWisps {
		wispPred = buildDescendantsPred("wisps", "w", "wisp_matches", wispWhereClauses, wispArgs)
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check Dolt/database connectivity (bd doctor, server logs) — the probe failure is a storage-layer symptom, not a filter problem
  2. Retry the command; transient connection drops between the wisp_dependencies probe and this probe are the usual cause
  3. Verify the wisps table is readable: run the same SELECT manually as the bd user and check grants
  4. If the database is corrupted or locked, restore from backup or run repairs before using GetDescendants

Example fix

// before: probing per call on a possibly-dead connection
page, err := repo.GetDescendants(ctx, rootID, filter)
// after: validate the store is reachable first
if err := store.Ping(ctx); err != nil {
    return fmt.Errorf("store unreachable: %w", err)
}
page, err := repo.GetDescendants(ctx, rootID, filter)
Defensive patterns

Strategy: retry

Validate before calling

if err := store.Ping(ctx); err != nil {
    return fmt.Errorf("store unreachable, aborting descendants walk: %w", err)
}

Try / catch

issues, err := repo.GetDescendants(ctx, rootID, filter)
if err != nil && strings.Contains(err.Error(), "wisps table probe") {
    // transient storage failure: retry with backoff
    return retryWithBackoff(3, func() error { _, err := repo.GetDescendants(ctx, rootID, filter); return err })
}

Prevention

When it happens

Trigger: Calling GetDescendants (or bd's hierarchical --parent walk) when the underlying `SELECT 1 FROM wisps LIMIT 1` probe fails with a non-missing-table error: the Dolt server dropped mid-query, the connection was closed, the database file is corrupted/locked, or the user lacks SELECT on the wisps table.

Common situations: Dolt server restarted or OOM-killed during a bd command; stale connection pool after a network blip; a partially-migrated database where wisps exists but is unreadable; running bd against a replica or read-only mount with restricted grants.

Related errors


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