gastownhall/beads · error

failed to get issue from %s: %w

Error message

failed to get issue from %s: %w

What it means

Returned by scanIssueFromTable when scanIssueFrom fails for a reason other than sql.ErrNoRows — i.e., the row was fetched but could not be scanned into the issue struct, or the query itself errored. The message includes the table name and wraps the underlying driver/scan error. Unlike the ErrNoRows case this indicates a genuine unexpected failure reading the issue.

Source

Thrown at internal/storage/dolt/wisps.go:40

	return issueops.InsertIssueIntoTable(ctx, tx, table, issue)
}

// scanIssueFromTable scans a single issue from the specified table.
//
//nolint:gosec // G201: table is a hardcoded constant ("issues" or "wisps")
func scanIssueFromTable(ctx context.Context, db *sql.DB, table, id string) (*types.Issue, error) {
	row := db.QueryRowContext(ctx, fmt.Sprintf(`
		SELECT %s
		FROM %s %s
		WHERE id = ?
	`, issueSelectColumns, table, sqlbuild.LeaseJoin(table)), id)

	issue, err := scanIssueFrom(row)
	if err == sql.ErrNoRows {
		return nil, fmt.Errorf("%w: issue %s", storage.ErrNotFound, id)
	}
	if err != nil {
		return nil, fmt.Errorf("failed to get issue from %s: %w", table, err)
	}
	return issue, nil
}

// generateIssueIDInTable generates a unique ID, checking for collisions
// in the specified table. Supports counter mode for non-ephemeral issues.
//
//nolint:gosec // G201: table is a hardcoded constant
func generateIssueIDInTable(ctx context.Context, tx *sql.Tx, table, prefix string, issue *types.Issue, actor string) (string, error) {
	// Counter mode only applies to the issues table (not wisps).
	if table == "issues" {
		counterMode, err := isCounterModeTx(ctx, tx)
		if err != nil {
			return "", err
		}
		if counterMode {
			return nextCounterIDTx(ctx, tx, prefix)
		}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped cause (%w) to see the exact scan/driver error
  2. Confirm the table schema matches the binary's expected columns (issueSelectColumns); run any available schema migration (e.g. bd doctor / migrate)
  3. Upgrade or downgrade bd so binary and database schema versions agree
  4. If a row is corrupt, restore from Dolt history or re-export/import the issue

Example fix

// before
// binary expects a column the DB lacks: scan fails with 'failed to get issue from wisps: ...'
// after
// run: bd doctor   (or the project's migrate step) to align schema, then retry the lookup
Defensive patterns

Strategy: try-catch

Validate before calling

// check schema alignment before lookups
rows, err := db.Query(`SHOW COLUMNS FROM wisps`)
if err != nil {
    return fmt.Errorf("wisps table missing or unreadable: %w", err)
}
// compare against expected columns / run bd doctor

Try / catch

issue, err := store.GetIssue(ctx, id)
if err != nil {
    var msg string
    if !errors.Is(err, storage.ErrNotFound) && strings.Contains(err.Error(), "failed to get issue from") {
        return fmt.Errorf("schema/driver problem reading issue: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: A SELECT from the wisps/issues table by ID succeeds in returning a row but scanIssueFrom fails: column/type mismatch after a schema change, NULL in a non-nullable-scanned column, or an underlying driver error during Scan/QueryRowContext.

Common situations: Running a newer bd binary against an older database (or vice versa) so issueSelectColumns doesn't match the actual table schema; corrupted rows; Dolt/driver version upgrades changing type mapping.

Related errors


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