gastownhall/beads · error

previewDelete: cascade expansion: %w

Error message

previewDelete: cascade expansion: %w

What it means

This error wraps a failure from issueRepo.FindAllDependents in previewDelete, which transitively expands the delete set to all dependents (the cascade). Without this expansion the preview could not show which issues disappear when cascade delete is enabled.

Source

Thrown at internal/storage/domain/issue_delete.go:321

	depRes, err := u.depRepo.ListByIssueIDs(ctx, ids, DepListOpts{Direction: DepDirectionOut})
	if err != nil {
		return preview, fmt.Errorf("previewDelete: list deps: %w", err)
	}
	for id, deps := range depRes.Outgoing {
		preview.DepRecords[id] = deps
	}
	wispDepRes, err := u.depRepo.ListByIssueIDs(ctx, ids, DepListOpts{Direction: DepDirectionOut, UseWispsTable: true})
	if err != nil && !dberrors.IsTableNotExist(err) {
		return preview, fmt.Errorf("previewDelete: list wisp deps: %w", err)
	}
	for id, deps := range wispDepRes.Outgoing {
		preview.DepRecords[id] = append(preview.DepRecords[id], deps...)
	}

	allIDs, err := u.issueRepo.FindAllDependents(ctx, ids)
	if err != nil {
		return preview, fmt.Errorf("previewDelete: cascade expansion: %w", err)
	}
	deletedSet := make(map[string]bool, len(allIDs))
	for _, id := range allIDs {
		deletedSet[id] = true
	}
	connected, _, err := u.collectConnectedIssues(ctx, allIDs, deletedSet)
	if err != nil {
		return preview, err
	}
	preview.ConnectedIssues = connected
	return preview, nil
}

func (u *issueUseCaseImpl) collectConnectedIssues(
	ctx context.Context, allIDs []string, deletedSet map[string]bool,
) (map[string]*types.Issue, map[string]bool, error) {
	out := map[string]*types.Issue{}
	isWisp := map[string]bool{}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Increase the query/statement timeout for the cascade lookup.
  2. Inspect the wrapped driver error and fix connectivity.
  3. Preview smaller id subsets to shrink the cascade.
  4. Retry — the preview is read-only and safe to re-run.
Defensive patterns

Strategy: retry

Validate before calling

// Bound the cascade before previewing: preview fewer ids at a time.
if len(ids) > maxBatch {
    return fmt.Errorf("preview batch too large (%d > %d); split it", len(ids), maxBatch)
}

Type guard

var dbErr *dberrors.DBError
if errors.As(err, &dbErr) {
    // inspect timeout vs connectivity codes
}

Try / catch

preview, err := uc.PreviewDelete(ctx, ids)
if err != nil && strings.Contains(err.Error(), "previewDelete: cascade expansion") {
    // often a timeout on deep graphs — retry with longer timeout or smaller batch
    return retryWithLongerTimeout(func() error { _, e := uc.PreviewDelete(ctx, ids); return e })
}

Prevention

When it happens

Trigger: PreviewDelete/PreviewDeleteWisp when the recursive dependent-lookup query fails: deep dependency graphs causing expensive/recursive queries, DB timeout, or connection loss.

Common situations: Very deep or cyclic-heavy dependency graphs making cascade expansion slow enough to hit statement timeouts; Dolt connection drops during long recursive queries.

Related errors


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