gastownhall/beads · error
failed to check issue existence: %w
Error message
failed to check issue existence: %w
What it means
This error wraps a failure of the follow-up SELECT status FROM issues WHERE id = ? that runs when the close UPDATE matched zero rows. That SELECT is needed to distinguish 'already closed' from 'not found'; if the query itself errors (driver, connection, scan), the close is aborted with this wrapped error. The original driver error is preserved via %w.
Source
Thrown at internal/storage/issueops/close.go:361
`, issueTable), types.StatusClosed, now, now, reason, session, freshRowLock(), id, types.StatusClosed)
if err != nil {
return nil, fmt.Errorf("failed to close issue: %w", err)
}
rows, err := result.RowsAffected()
if err != nil {
return nil, fmt.Errorf("failed to get rows affected: %w", err)
}
if rows == 0 {
var status string
qerr := tx.QueryRowContext(ctx,
fmt.Sprintf(`SELECT status FROM %s WHERE id = ?`, issueTable), id,
).Scan(&status)
if qerr == sql.ErrNoRows {
return nil, fmt.Errorf("%w: issue %s", storage.ErrNotFound, id)
}
if qerr != nil {
return nil, fmt.Errorf("failed to check issue existence: %w", qerr)
}
if types.Status(status) == types.StatusClosed {
return &CloseResult{IsWisp: isWisp, AlreadyClosed: true}, nil
}
return nil, fmt.Errorf("failed to close issue: %s", id)
}
// A closed issue holds no lease (no-op for wisps, which are never leased).
if err := DeleteLeaseInTx(ctx, tx, id); err != nil {
return nil, err
}
if recordEvent {
if err := RecordEventInTable(ctx, tx, eventTable, id, types.EventClosed, actor, reason); err != nil {
return nil, fmt.Errorf("failed to record event: %w", err)
}
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error with errors.Is/As to find the root cause (timeout, connection reset, scan type mismatch).
- Retry the close operation in a fresh transaction after confirming the DB is reachable.
- Increase the context deadline if timeouts are killing the diagnostic query.
- Check server logs for the failing query; verify the issues table schema is intact (bd doctor).
Defensive patterns
Strategy: try-catch
Try / catch
err := store.CloseIssue(ctx, id, actor, reason)
if err != nil && strings.Contains(err.Error(), "failed to check issue existence") {
if errors.Is(err, context.DeadlineExceeded) || isTransientNet(err) {
return retryClose(ctx, id, actor, reason, 1)
}
return err
} Prevention
- Use a generous context deadline so the diagnostic SELECT isn't cut off.
- Keep the connection stable — avoid canceling mid-operation.
- Verify schema integrity with bd doctor if scan errors recur.
- Retry transient network failures with backoff at the caller level.
When it happens
Trigger: tx.QueryRowContext(...).Scan() returns a non-ErrNoRows error during the existence check: connection failure inside the transaction, context cancellation, driver error, or datatype mismatch while scanning into the status string.
Common situations: Connection dropped between the failed UPDATE and the diagnostic SELECT; context timeout expiring mid-function; corrupted row data preventing scan; low-level driver bug under load.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- query dependency sources: %w
- query dependency targets: %w
- failed to begin transaction: %w
- failed to commit is_blocked repairs: %w
- failed to get federation peer: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/e9e059aefac7dc06.
Report an issue: GitHub.