gastownhall/beads · error

delete: check dependents: %w

Error message

delete: check dependents: %w

What it means

This wraps a failure from ExternalDependentsBySourceInTx while DeleteInTx checks whether rows outside the request depend on the ids being deleted (only when req.Cascade is false). The expected domain refusal is DependentsOutsideRequestError; this error means the dependents query itself failed before an answer could be produced. It is a wrapper around a storage/driver failure.

Source

Thrown at internal/storage/issueops/delete_role.go:109

		}
	}

	idSet := make(map[string]bool, len(ids))
	for _, id := range ids {
		idSet[id] = true
	}

	// The guard runs only when the request did not already say what to do
	// about dependents. Under Cascade there is nothing outside the set by
	// construction, which is why the expansion below is not asked about it.
	//
	// IT ASKS ABOUT EVERY NAMED ID, IN BOTH PLANES: the leaf says "a NAMED ROW
	// that some row OUTSIDE the request depends on is refused" with no wisp
	// exemption, and the unit-of-work body has always read it that way.
	if !req.Cascade {
		external, err := ExternalDependentsBySourceInTx(ctx, tx, ids, idSet)
		if err != nil {
			return publicops.DeleteResult{}, fmt.Errorf("delete: check dependents: %w", err)
		}
		if !req.Force {
			// Request order, so the id a caller is told about is stable
			// across runs and across backends.
			for _, id := range ids {
				if deps := external[id]; len(deps) > 0 {
					return publicops.DeleteResult{}, &publicops.DependentsOutsideRequestError{
						IssueID:    id,
						Dependents: deps,
					}
				}
			}
		} else {
			orphaned := make(map[string]bool)
			for _, deps := range external {
				for _, id := range deps {
					orphaned[id] = true
				}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped driver error; the message names the failing table ('query dependents from <table>')
  2. Confirm both dependencies and wisp_dependencies tables exist / migrations are applied
  3. Restore connectivity and retry the delete in a fresh transaction
  4. If timeouts, increase the context budget or delete in smaller batches
  5. If wisp_dependencies is intentionally absent on your backend, check whether optionalBlockedTable/isTableNotExistError covers your driver's error text
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check dependents outside the request using the public read path before deleting
external, err := store.ExternalDependents(ctx, ids)
if err != nil { return err }
if len(external) > 0 && !req.Cascade && !req.Force { return fmt.Errorf("blocked by dependents: %v", external) }

Type guard

var derr *publicops.DependentsOutsideRequestError
if errors.As(err, &derr) { /* expected refusal: derr.IssueID, derr.Dependents */ }
// else: 'delete: check dependents' wrapper => storage failure

Try / catch

_, err := store.Delete(ctx, req)
if err != nil && strings.Contains(err.Error(), "delete: check dependents") {
    // wrapped driver error; inspect cause, retry in fresh tx
}

Prevention

When it happens

Trigger: DeleteInTx with Cascade=false calls ExternalDependentsBySourceInTx; the SELECT against 'dependencies' or 'wisp_dependencies' fails for a non-'table not exist' reason (driver error, cancelled context, dead connection).

Common situations: Connection reset mid-delete; context timeout on a large batch; missing migration making the query error out rather than report table-not-exist; driver/backend version mismatch.

Related errors


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