gastownhall/beads · error

delete: partition

Error message

delete: partition: %w

What it means

deleteMany wraps errors from issueRepo.PartitionWispIDs, which splits the expanded ID set into wisps vs regular issues. The 'delete: partition:' prefix marks this step as the failure point. Deletion aborts before counting or deleting anything.

Solutions

  1. Inspect the wrapped driver error from PartitionWispIDs
  2. Verify Dolt connectivity and server health
  3. Retry the delete — no data has been modified yet at this stage
  4. For very large ID sets, delete in smaller batches

Example fix

// before
res, err := uc.DeleteWisps(ctx, ids, actor)
if err != nil { return err }
// after
if err != nil {
	if strings.Contains(err.Error(), "delete: partition") {
		// nothing deleted; retry after checking storage health
	}
	return fmt.Errorf("batch delete: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

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

Try / catch

res, err := uc.DeleteWisps(ctx, ids, actor)
if err != nil {
	if strings.Contains(err.Error(), "delete: partition") {
		// partition is read-only; nothing deleted — safe to retry
		return retryDelete(ctx, ids)
	}
	return err
}

Prevention

When it happens

Trigger: Any deleteMany invocation (via DeleteIssue, DeleteWisp, DeleteIssues, DeleteWisps) reaching the partition step when PartitionWispIDs fails — DB connection error, SQL error in the ID-classification query, storage unavailable.

Common situations: Bulk deletes of mixed issue/wisp sets during Dolt unavailability; schema drift between wisp and issue tables; very large ID lists hitting query limits.

Related errors


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

Appendix: source

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

			}
			result.OrphanedIssues = sortedStringSet(orphanSet)
		} else {
			for _, id := range params.IDs {
				if deps := externalBySource[id]; len(deps) > 0 {
					sort.Strings(deps)
					result.OrphanedIssues = deps
					return result, &DeleteBlockedError{IssueID: id, Dependents: deps}
				}
			}
		}
	}
	if len(allIDs) == 0 {
		return DeleteIssuesResult{}, nil
	}

	wispIDs, regularIDs, err := u.issueRepo.PartitionWispIDs(ctx, allIDs)
	if err != nil {
		return DeleteIssuesResult{}, fmt.Errorf("delete: partition: %w", err)
	}

	depCount, err := u.countDeletedDependencies(ctx, allIDs)
	if err != nil {
		return DeleteIssuesResult{}, err
	}
	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

View on GitHub (pinned to 71377f2769)