gastownhall/beads · error

delete: count wisp events: %w

Error message

delete: count wisp events: %w

What it means

deleteMany wraps errors from eventsRepo.CountAllForIDs on the wisps table (UseWispsTable: true) while counting pre-delete events. The 'delete: count wisp events:' prefix identifies this step; the underlying error is preserved. Deletion has not begun.

Source

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

	result.DependenciesCount = depCount

	labelIssue, err := u.labelRepo.CountAllForIDs(ctx, regularIDs, LabelOpts{})
	if err != nil {
		return DeleteIssuesResult{}, fmt.Errorf("delete: count labels: %w", err)
	}
	labelWisp, err := u.labelRepo.CountAllForIDs(ctx, wispIDs, LabelOpts{UseWispsTable: true})
	if err != nil {
		return DeleteIssuesResult{}, fmt.Errorf("delete: count wisp labels: %w", err)
	}
	result.LabelsCount = labelIssue + labelWisp

	evIssue, err := u.eventsRepo.CountAllForIDs(ctx, regularIDs, RecordEventOpts{})
	if err != nil {
		return DeleteIssuesResult{}, fmt.Errorf("delete: count events: %w", err)
	}
	evWisp, err := u.eventsRepo.CountAllForIDs(ctx, wispIDs, RecordEventOpts{UseWispsTable: true})
	if err != nil {
		return DeleteIssuesResult{}, fmt.Errorf("delete: count wisp events: %w", err)
	}
	result.EventsCount = evIssue + evWisp

	if params.DryRun {
		result.DeletedCount = len(regularIDs) + len(wispIDs)
		return result, nil
	}

	var connected map[string]*types.Issue
	var connectedIsWisp map[string]bool
	if params.UpdateTextReferences {
		deletedSet := make(map[string]bool, len(allIDs))
		for _, id := range allIDs {
			deletedSet[id] = true
		}
		connected, connectedIsWisp, err = u.collectConnectedIssues(ctx, allIDs, deletedSet)
		if err != nil {
			return result, err

View on GitHub (pinned to 71377f2769)

Solutions

  1. Unwrap the error chain for the wisp-events query failure
  2. Confirm the wisps table/schema matches the installed beads version (upgrade if needed)
  3. Retry the delete — safe, nothing modified yet
  4. Check Dolt connectivity and server logs

Example fix

// before
res, err := uc.DeleteWisps(ctx, ids, actor)
if err != nil { return err }
// after
if err != nil && strings.Contains(err.Error(), "count wisp events") {
	// pre-delete stats failed; no data changed — check wisp schema and retry
	return err
}
Defensive patterns

Strategy: retry

Validate before calling

if err := pingDolt(ctx); err != nil {
	return fmt.Errorf("storage unavailable: %w", err)
}

Try / catch

res, err := uc.DeleteWisps(ctx, ids, actor)
if err != nil && strings.Contains(err.Error(), "count wisp events") {
	// wisp events count failed before deletion — check schema, then retry
	return err
}

Prevention

When it happens

Trigger: Any deleteMany path where CountAllForIDs(ctx, wispIDs, RecordEventOpts{UseWispsTable: true}) fails — wisp events table inaccessible, SQL error, or connection failure.

Common situations: Wisp-heavy deletes after schema changes to wisp event storage; Dolt unavailability during automated cleanup jobs; permission problems on the wisps table.

Related errors


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