gastownhall/beads · error

count wisp dependencies: %w

Error message

count wisp dependencies: %w

What it means

DeleteResolvedSetInTx aborts a batch delete when it cannot count rows in the "wisp_dependencies" table for the wisp IDs being deleted. The error wraps the underlying SQL/driver error from CountRowsForIssueIDsInTx, so the real cause (connection loss, unknown table, context cancellation, syntax) is in the wrapped chain. It exists to compute the dependency count reported in a dry-run delete result.

Source

Thrown at internal/storage/issueops/delete.go:217

func DeleteResolvedSetInTx(ctx context.Context, tx *sql.Tx, set DeletionSet, dryRun bool) (*types.DeleteIssuesResult, error) {
	result := &types.DeleteIssuesResult{}
	if len(set.All) == 0 {
		return result, nil
	}

	deletedSet := make(map[string]bool, len(set.All))
	for _, id := range set.All {
		deletedSet[id] = true
	}

	var depsCount, labelsCount, eventsCount int
	var err error
	if depsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "dependencies", set.RegularIDs); err != nil {
		return nil, fmt.Errorf("count dependencies: %w", err)
	}
	wispDepsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_dependencies", set.WispIDs)
	if err != nil {
		return nil, fmt.Errorf("count wisp dependencies: %w", err)
	}
	depsCount += wispDepsCount

	if labelsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "labels", set.RegularIDs); err != nil {
		return nil, fmt.Errorf("count labels: %w", err)
	}
	wispLabelsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_labels", set.WispIDs)
	if err != nil {
		return nil, fmt.Errorf("count wisp labels: %w", err)
	}
	labelsCount += wispLabelsCount

	if eventsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "events", set.RegularIDs); err != nil {
		return nil, fmt.Errorf("count events: %w", err)
	}
	wispEventsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_events", set.WispIDs)
	if err != nil {
		return nil, fmt.Errorf("count wisp events: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped error with errors.Unwrap/%+v to find the driver-level cause (unknown table vs connection vs context deadline).
  2. Run the beads schema migration so wisp_dependencies exists (or confirm the driver supports wisp tables).
  3. Retry the delete; a transient connection or lock failure usually clears on a new transaction.
  4. Check Dolt server health and network connectivity if the wrapped error is connection-related.

Example fix

// before
result, err := store.DeleteInTx(ctx, tx, ids)
if err != nil {
    return fmt.Errorf("delete failed: %w", err)
}
// after
result, err := store.DeleteInTx(ctx, tx, ids)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        return fmt.Errorf("delete timed out, retrying: %w", err)
    }
    return fmt.Errorf("delete failed: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

// before deleting, verify wisp tables are reachable
var n int
if err := db.QueryRowContext(ctx, `SELECT COUNT(*) FROM wisp_dependencies LIMIT 1`).Scan(&n); err != nil {
    return fmt.Errorf("wisp_dependencies unreadable, run migrations: %w", err)
}

Try / catch

res, err := store.DeleteInTx(ctx, tx, ids)
if err != nil {
    if isTransient(err) { // e.g. driver.ErrBadConn / deadline
        res, err = store.DeleteInTx(ctx, tx, ids) // fresh tx, safe to retry
    }
    if err != nil {
        return fmt.Errorf("delete failed: %w", err)
    }
}

Prevention

When it happens

Trigger: Calling DeleteResolvedSetInTx (directly or via DeleteIssuesInTx/DeleteInTx) when the wisp_dependencies table is missing, corrupted, locked, or the underlying DB connection/transaction has failed. Also triggered by context cancellation or deadline expiry during the count query.

Common situations: Running against a database migrated from an older beads version that predates the wisp_dependencies table; a Dolt server restart or dropped connection mid-transaction; schema corruption; an embedded-mode driver without wisp tables.

Related errors


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