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
- Read the wrapped driver error; the message names the failing table ('query dependents from <table>')
- Confirm both dependencies and wisp_dependencies tables exist / migrations are applied
- Restore connectivity and retry the delete in a fresh transaction
- If timeouts, increase the context budget or delete in smaller batches
- 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
- Probe dependents with a read before issuing unforced deletes
- Ensure both dependency-plane migrations are applied
- Keep delete contexts short-lived but adequately timed
- Validate driver/backend version compatibility
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
- delete: resolve ids: %w
- delete: %w
- delete: check dependents: %w
- failed to remove federation peer: %w
- iter dependents: query: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/88845fabc84287ed.
Report an issue: GitHub.