gastownhall/beads · error
descendants: hydrate issues: %w
Error message
descendants: hydrate issues: %w
What it means
GetDescendants wraps a failure from fetchIssuesByIDs when hydrating the durable issue rows matched by the descendants walk. After the CTE returns IDs, each ID is loaded from the issues table (with optional label/dependency hydration); any SQL or hydration error there is wrapped as "descendants: hydrate issues". Unlike the wisps hydration, table-not-exist is NOT tolerated here because issues is a mandatory table.
Source
Thrown at internal/storage/domain/db/issue_descendants.go:90
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)
}
}
return reassembleBySrc(page.ordered, issuesByID, wispsByID), nil
}
// buildDescendantsCTE walks parent-child edges AND the dotted-ID fallback the
// classic ParentID filter applies (issueops/filters.go): a row named
// <node>.<suffix> with no parent-child edge at all is a child of <node>.
// Rows carry a via marker: 'e' for edge-found, 'd' for dotted-found. Dotted
// recursion only fires from 'e' rows — a dotted node's own dottedView on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped inner error to see whether the base fetch or the label/dependency hydration failed
- Run bd doctor to check mandatory tables (issues, labels, dependencies) exist and are consistent
- Retry on transient connection errors; shrink the result set with filter fields or MaxRows if the batch is huge
- Restore the database from backup if a required table is missing
Example fix
// before: assuming any hydration failure is transient
issues, err := repo.GetDescendants(ctx, root, filter)
// after: distinguish and diagnose
issues, err := repo.GetDescendants(ctx, root, filter)
if err != nil && strings.Contains(err.Error(), "hydrate issues") {
log.Printf("run bd doctor: mandatory table problem: %v", err)
} Defensive patterns
Strategy: validation
Validate before calling
if err := bdDoctor(ctx); err != nil {
return fmt.Errorf("mandatory tables broken, fix before GetDescendants: %w", err)
} Try / catch
issues, err := repo.GetDescendants(ctx, rootID, filter)
if err != nil && strings.Contains(err.Error(), "hydrate issues") {
if dberrors.IsTableNotExist(errors.Unwrap(err)) {
// schema is missing a mandatory table: restore/repair, do not retry
}
} Prevention
- Run bd doctor after migrations, clones, and version upgrades
- Never drop or rename issues/labels/dependencies manually
- Back up the database before schema changes
- Retry only transient errors; table-not-exist needs repair, not retry
When it happens
Trigger: Calling GetDescendants when the follow-up `SELECT ... FROM issues WHERE id IN (...)` or its hydrateIssues step (labels/dependencies) fails: missing issues/labels/dependencies tables, connection drop, scan error, or ctx cancellation.
Common situations: Corrupted or partially migrated database missing the labels or dependencies tables; too many descendant IDs producing an oversized IN clause / packet; connection pool exhausted during hydration.
Related errors
- search %s: hydrate: %w
- hydrate labels: %w
- iter issues: hydrate labels: %w
- failed to get wisp labels: %w
- descendants: hydrate wisps: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/dd09f1ddb9c0cbfb.
Report an issue: GitHub.