gastownhall/beads · error
descendants: query: %w
Error message
descendants: query: %w
What it means
GetDescendants wraps an error from r.runner.QueryContext executing the generated recursive CTE that walks parent-child edges (and dotted-ID fallbacks) across the issues and wisps tables. This is the raw SQL execution failure — syntax, engine, connection, or schema errors from the Dolt/MySQL backend — surfaced after the query was already assembled successfully.
Source
Thrown at internal/storage/domain/db/issue_descendants.go:81
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)
}
issuesByID, err := r.fetchIssuesByIDs(ctx, page.issueIDs, issuesFilterTables, filter)
if err != nil {
return nil, fmt.Errorf("descendants: hydrate issues: %w", err)
}
var wispsByID map[string]*types.Issue
if len(page.wispIDs) > 0 {
wispsByID, err = r.fetchIssuesByIDs(ctx, page.wispIDs, wispsFilterTables, filter)
if err != nil && !dberrors.IsTableNotExist(err) {
return nil, fmt.Errorf("descendants: hydrate wisps: %w", err)
}
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped driver error; if it mentions "unable to find field with index", upgrade/downgrade Dolt to a version without the recursive-CTE analyzer bug
- Run bd doctor to verify schema completeness (issues, wisps, dependencies, wisp_dependencies all present and consistent)
- Increase the context timeout or check cancellation if the error is context deadline/canceled
- Retry on transient connection errors; check Dolt server logs for the failing query
Example fix
// before: bare context that expires mid-walk ctx := context.Background() issues, err := repo.GetDescendants(ctx, root, filter) // after: give deep hierarchy walks room ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() issues, err := repo.GetDescendants(ctx, root, filter)
Defensive patterns
Strategy: retry
Try / catch
issues, err := repo.GetDescendants(ctx, rootID, filter)
var netErr net.Error
if err != nil && (errors.Is(err, context.DeadlineExceeded) || errors.As(err, &netErr)) {
// retry with a longer deadline
} Prevention
- Keep Dolt engine version aligned with the version bd was built against (recursive-CTE analyzer bugs are version-specific)
- Run bd doctor after upgrades to confirm schema compatibility
- Use generous context timeouts for deep hierarchy walks
- Monitor Dolt server logs for analyzer/query errors
When it happens
Trigger: Calling GetDescendants when the WITH RECURSIVE descendants query fails server-side: engine analyzer bugs (e.g. the documented dolt 2.1.6 "unable to find field with index N" issue), missing tables/columns, connection drop, or cancellation of ctx mid-query.
Common situations: Running an older or newer Dolt engine with a known recursive-CTE analyzer bug; a database migrated from the pre-wisps schema missing wisp tables the CTE references; long-running walk killed by context timeout.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- db: ListRemotes: query: %w
- ErrQuery
- failed to begin transaction: %w
- failed to recompute is_blocked: %w
- failed to commit is_blocked repairs: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/995966bb508ce765.
Report an issue: GitHub.