gastownhall/beads · error
failed to get epics: %w
Error message
failed to get epics: %w
What it means
GetEpicsEligibleForClosureInTx first queries for non-closed epic issue IDs. If that query fails at execution time (bad SQL, missing table, connection error), the function aborts with this message. It means epic closure analysis could not even start because the initial epic list could not be fetched.
Source
Thrown at internal/storage/issueops/epic_closure.go:20
import (
"context"
"fmt"
"github.com/steveyegge/beads/internal/types"
)
// GetEpicsEligibleForClosureInTx returns epics whose children are all closed.
// nolint:gosec // G201: table names are hardcoded, placeholders contain only ? markers
func GetEpicsEligibleForClosureInTx(ctx context.Context, tx DBTX) ([]*types.EpicStatus, error) {
// Step 1: Get open epic IDs (single-table scan)
epicRows, err := tx.QueryContext(ctx, `
SELECT id FROM issues
WHERE issue_type = 'epic'
AND status != 'closed'
`)
if err != nil {
return nil, fmt.Errorf("failed to get epics: %w", err)
}
var epicIDs []string
for epicRows.Next() {
var id string
if err := epicRows.Scan(&id); err != nil {
epicRows.Close()
return nil, fmt.Errorf("scan epic id: %w", err)
}
epicIDs = append(epicIDs, id)
}
epicRows.Close()
if len(epicIDs) == 0 {
return nil, nil
}
// Step 2: Get parent-child dependencies from both tables (bd-w2w)
// Wisp children store their parent-child deps in wisp_dependencies,View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error (%w) for 'no such table'/'unknown column' and run pending migrations.
- Verify the database is reachable and the schema has an `issues` table with `issue_type` and `status` columns.
- Re-run the command; transient lock/connection failures usually clear on retry.
- Restore the database from backup if the schema is corrupted.
Defensive patterns
Strategy: validation
Validate before calling
var hasIssues int
err := db.QueryRow("SELECT COUNT(*) FROM information_schema.tables WHERE table_name = 'issues'").Scan(&hasIssues)
if err != nil || hasIssues == 0 { return errors.New("run bd migrations before closure analysis") } Type guard
func isEpicQueryFailed(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to get epics:")
} Try / catch
epics, err := GetEpicsEligibleForClosureInTx(ctx, tx)
if err != nil {
var sqliteErr *sqlite.Error // or mysql.MySQLError
if errors.As(err, &sqliteErr) { return runMigrationsThenRetry(ctx) }
return err
} Prevention
- Always run `bd migrate`/upgrades before running maintenance commands.
- Never hand-edit the database schema.
- Verify DB reachability before long maintenance runs.
- Take a backup before epic closure operations.
When it happens
Trigger: Calling GetEpicsEligibleForClosureInTx (via epic closure/cleanup commands) when the `SELECT id FROM issues WHERE issue_type = 'epic' AND status != 'closed'` query errors — corrupted schema, locked database, or connection failure.
Common situations: Running `bd` commands against a partially migrated or hand-edited database where the issues table or issue_type column is missing; the Dolt server being shut down mid-command.
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 batch-fetch child statuses from %s: %w
- failed to batch-fetch epic issues: %w
- get events: %w
- querying epics: %w
- querying blocked issues: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/fdaa8b1a264e9d22.
Report an issue: GitHub.