gastownhall/beads · error
deferred parents: check %s: %w
Error message
deferred parents: check %s: %w
What it means
Wraps an unexpected error from the deferred-parent existence probe in anyFutureDeferredParent, which checks `issues` then `wisps` for any row with defer_until in the future. ErrNoRows and missing-table errors are tolerated (the probe just moves on); anything else is fatal and wrapped here with the table name. This protects ready work from silently proceeding with an unknown deferred set.
Source
Thrown at internal/storage/domain/db/ready_work.go:86
return nil, err
}
return r.descendantsOfFutureDeferredParents(ctx)
}
func (r *issueSQLRepositoryImpl) anyFutureDeferredParent(ctx context.Context) (bool, error) {
for _, table := range []string{"issues", "wisps"} {
var probe int
//nolint:gosec // G201: table is a hardcoded constant.
err := r.runner.QueryRowContext(ctx, fmt.Sprintf(
`SELECT 1 FROM %s WHERE defer_until IS NOT NULL AND defer_until > UTC_TIMESTAMP() LIMIT 1`,
table)).Scan(&probe)
switch {
case err == nil:
return true, nil
case errors.Is(err, sql.ErrNoRows), dberrors.IsTableNotExist(err):
continue
default:
return false, fmt.Errorf("deferred parents: check %s: %w", table, err)
}
}
return false, nil
}
func (r *issueSQLRepositoryImpl) descendantsOfFutureDeferredParents(ctx context.Context) ([]string, error) {
var childIDs []string
for _, e := range deferredParentEdges {
//nolint:gosec // G201: depTable/issueTable/targetCol are hardcoded.
q := fmt.Sprintf(`
SELECT dep.issue_id
FROM %s dep
JOIN %s parent ON parent.id = dep.%s
WHERE dep.type = 'parent-child'
AND parent.defer_until IS NOT NULL
AND parent.defer_until > UTC_TIMESTAMP()
`, e.depTable, e.issueTable, e.targetCol)
rows, err := r.runner.QueryContext(ctx, q)View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped driver error and the probed table name to pinpoint the cause
- Fix connectivity/credentials so SELECT on issues/wisps works
- Verify table integrity/schema for the probed table
- Retry once transient server issues clear
Defensive patterns
Strategy: retry
Validate before calling
// check connectivity and SELECT grants before ready-work calls
if err := db.PingContext(ctx); err != nil { return err }
var probe int
if err := db.QueryRow("SELECT 1 FROM issues LIMIT 1").Scan(&probe); err != nil {
return fmt.Errorf("no SELECT access to issues: %w", err)
} Type guard
func isDeferredProbeError(err error) bool {
return err != nil && strings.Contains(err.Error(), "deferred parents: check ")
} Try / catch
ready, err := repo.GetReadyWork(ctx, filter)
if isDeferredProbeError(err) {
// transient server/permission issue: back off and retry, or surface to ops
time.Sleep(backoff)
ready, err = repo.GetReadyWork(ctx, filter)
} Prevention
- Grant SELECT on issues/wisps to the app DB user
- Health-check the DB before ready-work computation
- Keep schema aligned with the beads version in use
- Use IncludeDeferred=true to bypass the probe when acceptable
When it happens
Trigger: Running the ready-work deferred-parent check when the probe SELECT against `issues` or `wisps` fails with something other than ErrNoRows/TableNotExist — e.g. connection refused, permission denied, or SQL syntax/engine error.
Common situations: Revoked DB credentials lacking SELECT on the probed table; server outage mid-check; schema corruption; engine errors like UTC_TIMESTAMP unavailability in odd configurations.
Related errors
- descendants: wisp_dependencies probe: %w
- descendants: wisps table probe: %w
- search wisps (merge): probe: %w
- get ready work: compute deferred parent children: %w
- deferred parents: %s/%s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/1f2741a135a564fe.
Report an issue: GitHub.