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

  1. Inspect the wrapped driver error from GetIssuesByIDsInTx
  2. Retry the delete in a fresh transaction — the delete rolls back atomically, so retry is safe
  3. Raise the context timeout when deleting ids with very large neighborhoods
  4. 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

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


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