gastownhall/beads · error

descendants: %w

Error message

descendants: %w

What it means

GetDescendants wraps a failure from scanIDSrcPage, which reads the (id, src) rows produced by the descendants CTE and splits them into issue IDs and wisp IDs. The scan loop can fail on rows.Scan (a column type mismatch) or on rows.Err() (a mid-iteration connection/engine failure). Since the query only projects two string columns, this usually means the stream broke mid-read.

Source

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

			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)
		}
	}

	return reassembleBySrc(page.ordered, issuesByID, wispsByID), nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped inner error: connection errors warrant retrying the whole GetDescendants call
  2. Reduce result size with filter.Limit/MaxRows so the scan completes within connection limits
  3. Verify Dolt server stability (logs, memory) if failures recur on large walks
  4. If it is a scan-type error, ensure the bd binary and database schema are the same version

Example fix

// before
issues, err := repo.GetDescendants(ctx, root, types.IssueFilter{})
// after: bound the walk so the result stream stays small
issues, err := repo.GetDescendants(ctx, root, types.IssueFilter{MaxRows: 10000})
Defensive patterns

Strategy: retry

Try / catch

issues, err := repo.GetDescendants(ctx, rootID, filter)
if err != nil && strings.HasSuffix(strings.TrimPrefix(err.Error(), "descendants: "), "rows") || strings.Contains(err.Error(), "scan") {
    // result stream broke mid-read: retry the whole call
}

Prevention

When it happens

Trigger: Calling GetDescendants when the result stream from the recursive CTE fails while being read: connection dropped between QueryContext and full row consumption, driver scan error, or ctx canceled during iteration.

Common situations: Large hierarchies whose scan outlasts a network idle timeout; Dolt server killed mid-result; driver/driver-version mismatch producing unexpected column types.

Related errors


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