gastownhall/beads · error

delete: resolve ids: %w

Error message

delete: resolve ids: %w

What it means

The unit-of-work delete path failed to resolve the requested ids into rows: loading via GetIssuesByIDs or GetWispsByIDs returned an error. The delete aborts before any dependent checks or removal happen, so no data was changed.

Source

Thrown at internal/storage/uow/deleter.go:99

// issueops.Deleter promises that a dry run refuses exactly where the real run
// refuses.
func deleteInUOW(ctx context.Context, uw UnitOfWork, req publicops.DeleteRequest) (publicops.DeleteResult, error) {
	issueUC := uw.IssueUseCase()
	result := publicops.DeleteResult{DryRun: req.DryRun}

	// The existence probe comes FIRST, so a request naming a typo reports the
	// typo rather than whatever the graph says about the ids that resolved. It
	// keeps the ROWS rather than a set of ids, because the version precondition
	// below needs their RowVersion and re-reading them for it would be a second
	// read of the same rows in the same transaction.
	present := make(map[string]*types.Issue, len(req.IDs))
	for _, load := range []func(context.Context, []string) ([]*types.Issue, error){
		issueUC.GetIssuesByIDs,
		issueUC.GetWispsByIDs,
	} {
		rows, err := load(ctx, req.IDs)
		if err != nil {
			return publicops.DeleteResult{}, fmt.Errorf("delete: resolve ids: %w", err)
		}
		for _, row := range rows {
			if row != nil {
				present[row.ID] = row
			}
		}
	}
	var missing []string
	for _, id := range req.IDs {
		if present[id] == nil {
			missing = append(missing, id)
		}
	}
	if len(missing) > 0 {
		return publicops.DeleteResult{}, &publicops.NotFoundError{IDs: missing}
	}

	// The version precondition, between the existence probe and the dependents

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry the delete once the wrapped DB error's cause is fixed
  2. Check the inner error for connection/timeout problems and restore DB connectivity
  3. Verify the ids are well-formed; malformed ids should fail validation earlier, so an error here is usually infrastructural
Defensive patterns

Strategy: retry

Validate before calling

for _, id := range req.IDs {
    if !strings.HasPrefix(id, "bd-") { return fmt.Errorf("malformed id %q", id) }
}

Try / catch

res, err := deleteInUOW(ctx, req)
if err != nil && strings.Contains(err.Error(), "delete: resolve ids") {
    // transient DB failure likely; retry after backoff
    return retryWithBackoff(func() error { return deleteInUOW(ctx, req) })
}

Prevention

When it happens

Trigger: deleteInUOW iterates the two loaders with the request's id list and one of the backing queries fails — DB error, connection loss, or a storage-layer failure while fetching issues or wisps by id.

Common situations: Database unavailable or restarted mid-request; corrupt index; transient Dolt transaction error during bulk delete requests.

Related errors


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