gastownhall/beads · error
classify child-count target in issues: %w
Error message
classify child-count target in issues: %w
What it means
Beads throws this when the probe 'SELECT 1 FROM issues WHERE id = ?' used to classify a close-policy target fails with a non-'no rows' error. Only sql.ErrNoRows is an acceptable outcome (meaning the id is not a durable issue); any other driver error is wrapped and aborts target classification for the open-children count.
Source
Thrown at internal/storage/issueops/close.go:273
func releaseCloseCheckedSavepoint(ctx context.Context, tx DBTX, name string) error {
//nolint:gosec // G201: name is generated by createCloseCheckedSavepoint.
if _, err := tx.ExecContext(ctx, "RELEASE SAVEPOINT "+name); err != nil {
return fmt.Errorf("release checked close savepoint: %w", err)
}
return nil
}
// dependencyTargetColumnForIDInTx returns the typed target column for id,
// preferring a durable row when an id is present in both tables.
func dependencyTargetColumnForIDInTx(ctx context.Context, tx DBTX, id string) (string, error) {
var found int
err := tx.QueryRowContext(ctx, "SELECT 1 FROM issues WHERE id = ?", id).Scan(&found)
if err == nil {
return "depends_on_issue_id", nil
}
if !errors.Is(err, sql.ErrNoRows) {
return "", fmt.Errorf("classify child-count target in issues: %w", err)
}
err = tx.QueryRowContext(ctx, "SELECT 1 FROM wisps WHERE id = ?", id).Scan(&found)
if err == nil {
return "depends_on_wisp_id", nil
}
if optionalBlockedTable("wisps") && isTableNotExistError(err) {
return "depends_on_issue_id", nil
}
if !errors.Is(err, sql.ErrNoRows) {
return "", fmt.Errorf("classify child-count target in wisps: %w", err)
}
return "depends_on_issue_id", nil
}
// isClosedInTx reports whether the issue (or wisp) identified by id exists and
// is already closed. It probes the issues table then the optional wisps table,
// mirroring IsBlockedInTx's table order.
//View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped driver error after 'classify child-count target in issues:' for the root cause
- Restore connectivity / retry the close if the cause was transient
- Run schema checks/migrations if issues is reported missing — unlike wisp tables, issues is mandatory
- Widen or remove context deadlines if the probe times out
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: issues is mandatory; verify it exists and is readable
var one int
if err := db.QueryRow("SELECT 1 FROM issues LIMIT 1").Scan(&one); err != nil {
return fmt.Errorf("issues table not readable (run migrations?): %w", err)
} Try / catch
count, err := countOpenChildrenInTx(ctx, tx, id)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || dberrors.IsConnectionError(err) || dberrors.IsLockTimeout(err) {
return retryClose(ctx, id)
}
return fmt.Errorf("close of %s failed: %w", id, err)
} Prevention
- Apply migrations so the mandatory issues table always exists before using beads
- Set context timeouts appropriate for your database latency
- Retry closes on transient connection/lock errors — they are transactional
- Monitor DB privileges after role changes; SELECT on issues is required
When it happens
Trigger: countOpenChildrenInTx → dependencyTargetColumnForIDInTx when the issues table is unreadable: missing issues table (error 1146 without optional-table gating applying — issues is not optional), permission denied, connection failure, lock timeout, or context cancellation during the probe.
Common situations: Database connection dropped mid-close; schema so broken the issues table is missing; another process holds locks on issues; context deadline exceeded on a slow server.
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
- failed to begin transaction: %w
- failed to recompute is_blocked: %w
- failed to commit is_blocked repairs: %w
- %s: %w
- failed to query orphaned dependencies: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6a97f9bdb1005e37.
Report an issue: GitHub.