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

  1. Inspect the wrapped error (%w) for 'no such table'/'unknown column' and run pending migrations.
  2. Verify the database is reachable and the schema has an `issues` table with `issue_type` and `status` columns.
  3. Re-run the command; transient lock/connection failures usually clear on retry.
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/fdaa8b1a264e9d22. Report an issue: GitHub.