gastownhall/beads · error
hydrate neighbors: %w
Error message
hydrate neighbors: %w
What it means
After collecting surviving neighbor ids, deleteNeighborsInTx hydrates them into full Issue rows via GetIssuesByIDsInTx so their text can be rewritten. This wrapper marks a failure in that hydration step. Per the source comment, external: targets and rows belonging to another repository name legitimately resolve to nothing and are simply absent — this error is for genuine lookup failures, not missing cross-repo rows.
Source
Thrown at internal/storage/issueops/delete_role.go:304
}
_ = rows.Close()
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate neighbors from %s: %w", depTable, err)
}
}
}
if len(neighborIDs) == 0 {
return nil, nil
}
// Sorted so the rewrite touches rows in a stable order, which is what
// makes a partially-applied failure reproducible.
hydrate := workapi.SortedDeleteIDs(neighborIDs)
// An `external:` target and a target belonging to another repository name
// no row here; GetIssuesByIDsInTx simply does not return them.
issues, err := GetIssuesByIDsInTx(ctx, tx, hydrate, nil)
if err != nil {
return nil, fmt.Errorf("hydrate neighbors: %w", err)
}
return issues, nil
}
// RewriteDeletedReferencesInTx replaces every word-boundary occurrence of a
// deleted id with `[deleted:<id>]` in each neighbor's description, notes,
// design and acceptance criteria, and reports how many ROWS it changed.
//
// Exported because the unit-of-work body needs the same rule and neither
// implementation may own it: a route that spelled the pattern differently
// would rewrite a different set of citations for the same deletion.
func RewriteDeletedReferencesInTx(ctx context.Context, tx DBTX, deletedIDs []string, neighbors []*types.Issue, actor string) (int, error) {
if len(neighbors) == 0 {
return 0, nil
}
touched := make(map[string]bool)
for _, id := range deletedIDs {
re := DeletedReferencePattern(id)View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped driver error from GetIssuesByIDsInTx
- Retry the delete in a fresh transaction — the delete rolls back atomically, so retry is safe
- Raise the context timeout when deleting ids with very large neighborhoods
- Check issues-table health/migrations if the failure reproduces on the same ids
Defensive patterns
Strategy: retry
Validate before calling
// ensure neighbor hydration will find rows in this repo; cross-repo/external: ids are legitimately skipped
if err := ctx.Err(); err != nil { return err } Try / catch
err := store.Delete(ctx, req)
if err != nil && strings.Contains(err.Error(), "hydrate neighbors") {
// GetIssuesByIDsInTx failed; storage issue, retry with fresh tx
} Prevention
- Use DryRun to exercise the full read path (including hydration) before committing
- Keep context timeouts proportional to neighborhood size
- Check issues-table health if failures repeat on the same ids
- Remember external:/cross-repo targets hydrating to nothing is normal, not an error
When it happens
Trigger: deleteNeighborsInTx calls GetIssuesByIDsInTx(hydrate, nil) over sorted neighbor ids and the batched lookup fails — driver error, context cancellation, or connection loss inside the delete transaction.
Common situations: Connection dropped after long neighbor scans; context timeout on a wide neighborhood; backend query failure on the issues table; transaction invalidated by a prior backend error.
Related errors
- descendants: hydrate issues: %w
- descendants: hydrate wisps: %w
- search %s: hydrate: %w
- hydrate labels: %w
- hydrate dependencies: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c8a6ea13adeb0f20.
Report an issue: GitHub.