gastownhall/beads · error
rewrite refs %s: %w
Error message
rewrite refs %s: %w
What it means
Wraps a failure from issueRepo.Update while rewriting textual references to a deleted issue inside a connected issue's description/notes/design/acceptance_criteria. After deletion, references like `bd-123` are replaced with `[deleted:bd-123]`; if the row update fails, the whole deleteMany aborts with this error naming the failing connected issue ID.
Source
Thrown at internal/storage/domain/issue_delete.go:425
updates := map[string]any{}
if re.MatchString(conn.Description) {
updates["description"] = re.ReplaceAllString(conn.Description, replacement)
}
if conn.Notes != "" && re.MatchString(conn.Notes) {
updates["notes"] = re.ReplaceAllString(conn.Notes, replacement)
}
if conn.Design != "" && re.MatchString(conn.Design) {
updates["design"] = re.ReplaceAllString(conn.Design, replacement)
}
if conn.AcceptanceCriteria != "" && re.MatchString(conn.AcceptanceCriteria) {
updates["acceptance_criteria"] = re.ReplaceAllString(conn.AcceptanceCriteria, replacement)
}
if len(updates) == 0 {
continue
}
opts := IssueTableOpts{UseWispsTable: isWisp[connID]}
if err := u.issueRepo.Update(ctx, connID, updates, actor, opts); err != nil {
return len(touched), fmt.Errorf("rewrite refs %s: %w", connID, err)
}
touched[connID] = true
if desc, ok := updates["description"].(string); ok {
conn.Description = desc
}
if notes, ok := updates["notes"].(string); ok {
conn.Notes = notes
}
if design, ok := updates["design"].(string); ok {
conn.Design = design
}
if ac, ok := updates["acceptance_criteria"].(string); ok {
conn.AcceptanceCriteria = ac
}
}
}
return len(touched), nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped driver error: fix locks/connectivity first (the failing issue ID is embedded in the message).
- Retry the delete once the database is idle; avoid concurrent bd writers on the same store.
- Check whether the target row still exists — a concurrently deleted neighbor makes the UPDATE fail.
- If context cancellation is the cause, run the delete with a dedicated long-timeout context.
- Manually resolve the reference in the named issue, then retry the delete.
Example fix
// before: two concurrent bd processes delete/update at once // error: rewrite refs bd-42: database is locked // after: serialize mutations (single writer, or an external lock) lock := acquireStoreLock() defer lock.Release() deleteErr := deleter.DeleteMany(ctx, ids)
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the target issues still exist before the delete triggers rewrites
for _, id := range connectedIDs {
if _, err := usecase.GetIssue(ctx, id); err != nil {
return fmt.Errorf("connected issue %s unavailable: %w", id, err)
}
} Type guard
func isRewriteRefsErr(err error) (string, bool) {
if err == nil { return "", false }
var id string
if _, scanErr := fmt.Sscanf(err.Error(), "rewrite refs %s:", &id); scanErr == nil {
return id, true
}
return "", false
} Try / catch
err := usecase.DeleteMany(ctx, ids)
if err != nil && strings.Contains(err.Error(), "rewrite refs ") {
// extract failing issue id from message, check locks/row state, retry
cause := errors.Unwrap(err)
return fmt.Errorf("delete aborted during ref rewrite: %w", cause)
} Prevention
- Serialize deletes — never run two mutation commands on the same store concurrently
- Use a long-timeout context for deletes that touch many connected issues
- Handle 'already exists / not found' driver errors idempotently in retry loops
- Keep batches small so a mid-batch storage failure is cheap to retry
When it happens
Trigger: deleteMany where a surviving neighbor issue contains a textual reference to a deleted ID and the UPDATE on that neighbor (issues or wisps table depending on isWisp) fails — DB lock, connection error, context canceled, or constraint violation.
Common situations: Deleting issues concurrently with another writer holding row locks; database going away mid-batch; updating a wisp row in a store whose wisp table is in a bad state; long-running deletes hitting driver timeouts.
Related errors
- delete: drop deps: %w
- delete: drop wisp deps: %w
- delete: drop labels: %w
- delete: drop events: %w
- delete: drop issue rows: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/09cd508b190e3b82.
Report an issue: GitHub.