gastownhall/beads · error

get events: %w

Error message

get events: %w

What it means

GetEventsInTx builds a parameterized query against the events table (with optional filters and LIMIT) and executes it. Any query-execution failure is wrapped as 'get events'. It means the event history could not be read, commonly due to filter/limit issues or database unavailability.

Source

Thrown at internal/storage/issueops/events.go:32

//nolint:gosec // G201: table is hardcoded via WispTableRouting
func GetEventsInTx(ctx context.Context, tx DBTX, issueID string, limit int) ([]*types.Event, error) {
	_, _, eventTable, _ := WispTableRouting(IsActiveWispInTx(ctx, tx, issueID))

	query := fmt.Sprintf(`
		SELECT id, issue_id, event_type, actor, old_value, new_value, comment, created_at
		FROM %s
		WHERE issue_id = ?
		ORDER BY created_at DESC
	`, eventTable)
	args := []interface{}{issueID}

	if limit > 0 {
		query += fmt.Sprintf(" LIMIT %d", limit)
	}

	rows, err := tx.QueryContext(ctx, query, args...)
	if err != nil {
		return nil, fmt.Errorf("get events: %w", err)
	}
	defer rows.Close()

	return scanEvents(rows)
}

// GetAllEventsSinceInTx returns all events created after the given time,
// querying both events and wisp_events tables.
func GetAllEventsSinceInTx(ctx context.Context, tx *sql.Tx, since time.Time) ([]*types.Event, error) {
	rows, err := tx.QueryContext(ctx, `
		SELECT id, issue_id, event_type, actor, old_value, new_value, comment, created_at
		FROM events
		WHERE created_at > ?
		UNION ALL
		SELECT id, issue_id, event_type, actor, old_value, new_value, comment, created_at
		FROM wisp_events
		WHERE created_at > ?
		ORDER BY created_at ASC

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped cause: 'no such table: events' means run migrations; 'unknown column' means schema drift.
  2. Retry if the cause is a lock or transient connection error.
  3. Verify filter parameters (issue_id, event_type, since) are valid values/columns.
  4. Check connectivity to the Dolt database.
Defensive patterns

Strategy: try-catch

Validate before calling

var hasEvents int
_ = db.QueryRow("SELECT COUNT(*) FROM information_schema.tables WHERE table_name='events'").Scan(&hasEvents)
if hasEvents == 0 { return errors.New("events table missing; run migrations") }
if limit < 0 { return errors.New("limit must be >= 0") }

Type guard

func isGetEventsErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "get events:")
}

Try / catch

events, err := GetEventsInTx(ctx, tx, opts)
if err != nil {
    if isGetEventsErr(err) && strings.Contains(err.Error(), "no such table") {
        return migrateThenRetry(ctx)
    }
    return fmt.Errorf("could not read events: %w", err)
}

Prevention

When it happens

Trigger: Calling GetEventsInTx when the composed SELECT on events fails — unknown filter column, malformed limit, connection error, or missing events table.

Common situations: Querying events with an issue_id that hits an index/schema mismatch; pre-migration databases lacking the events table; database locked by another writer.

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/dc99b63e1046f459. Report an issue: GitHub.