gastownhall/beads · error
descendants: wisps filter: %w
Error message
descendants: wisps filter: %w
What it means
GetDescendants wraps a failure from buildIssueFilterClauses when building the WHERE clauses for the wisps branch of the recursive descendants CTE. The same filter was already built successfully against the issues table, so a failure here almost always means a filter clause is invalid specifically for the wisps table layout (e.g. a column exists in one table config but not the other).
Source
Thrown at internal/storage/domain/db/issue_descendants.go:67
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)
}
cte, allArgs := buildDescendantsCTE(rootID, walkWisps, issuePred, wispPred)
rows, err := r.runner.QueryContext(ctx, cte, allArgs...)
if err != nil {
return nil, fmt.Errorf("descendants: query: %w", err)
}
page, err := scanIDSrcPage(rows)
if err != nil {
return nil, fmt.Errorf("descendants: %w", err)View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped inner error to identify which filter clause failed to build
- Remove or simplify the offending filter field and re-run GetDescendants
- Check that the database schema matches the bd version (run bd doctor / migrations)
- Set SkipWisps=true in the filter if you only need durable issues and the wisps plane is problematic
Example fix
// before
issues, err := repo.GetDescendants(ctx, root, types.IssueFilter{Assignee: &a, Ephemeral: &t})
// after: drop fields unsupported on the wisps plane, or scope to issues only
issues, err := repo.GetDescendants(ctx, root, types.IssueFilter{Assignee: &a, SkipWisps: true}) Defensive patterns
Strategy: validation
Validate before calling
// build the filter clauses yourself first; if this fails, the filter is bad
if _, _, err := sqlbuild.BuildIssueFilterClauses("", filter, sqlbuild.WispsFilterTables); err != nil {
return fmt.Errorf("filter unsupported on wisps plane: %w", err)
} Try / catch
issues, err := repo.GetDescendants(ctx, rootID, filter)
if err != nil && strings.Contains(err.Error(), "wisps filter") {
// fall back to durable issues only
filter.SkipWisps = true
issues, err = repo.GetDescendants(ctx, rootID, filter)
} Prevention
- Only use filter fields documented as valid for both planes
- Test new filter combinations against a workspace containing wisps
- Pin database schema version to the bd binary version
- Prefer SkipWisps=true when wisps data is irrelevant to the query
When it happens
Trigger: Calling GetDescendants with an IssueFilter whose clauses reference wisp-incompatible fields, when the wisps table exists and is non-empty and SkipWisps is false — i.e. buildIssueFilterClauses("", levelFilter, wispsFilterTables) returns an error.
Common situations: Using a filter field supported on durable issues but not on the wisps plane after a schema/config divergence; version mismatch where an older database lacks a column the filter builder expects in wispsFilterTables.
Related errors
- db: DependencySQLRepository.CycleThroughEdges (wisps): %w
- db: DependencySQLRepository.WispSourceIDs: %w
- db: DependencySQLRepository.GetWispDependencyRecordsForIDs:
- descendants: hydrate wisps: %w
- search wisps (ephemeral filter): %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/90dd658b80ecf07d.
Report an issue: GitHub.