gastownhall/beads · error

get federation peer

Error message

get federation peer: %w

What it means

The SELECT of the federation peer row failed at the SQL level (not ErrNoRows); the driver error is wrapped as "get federation peer". This signals a database-side problem such as a missing table, schema mismatch, or connection failure, not an absent peer. Check the wrapped driver error.

Solutions

  1. Read the wrapped driver error to identify the root cause
  2. Run pending schema migrations so federation_peers has the expected columns
  3. Retry the transaction if the error was transient
  4. Verify the transaction is still active and not rolled back

Example fix

// before
peer, err := issueops.GetFederationPeerInTx(ctx, tx, name) // fails: unknown column sovereignty
// after
if err := migrate(ctx, db); err != nil { // bring schema current
    return err
}
peer, err := issueops.GetFederationPeerInTx(ctx, tx, name)
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure schema is current before reading
if err := migrate(ctx, db); err != nil {
    return err
}

Try / catch

peer, err := issueops.GetFederationPeerInTx(ctx, tx, name)
if err != nil && !errors.Is(err, storage.ErrNotFound) {
    log.Printf("get federation peer %s failed: %v", name, err)
    return fmt.Errorf("lookup peer %s: %w", name, err)
}

Prevention

When it happens

Trigger: tx.QueryContext/Scan on federation_peers returns a driver error: table missing, column mismatch, connection dropped, or transaction aborted.

Common situations: Older database without federation_peers (migration not run); Dolt server restarted mid-transaction; column added/renamed in a version change.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

Thrown at internal/storage/issueops/federation.go:80

// Returns storage.ErrNotFound (wrapped) if the peer does not exist.
func GetFederationPeerInTx(ctx context.Context, tx *sql.Tx, name string) (*FederationPeerRow, error) {
	var row FederationPeerRow
	var lastSync sql.NullTime
	var username sql.NullString

	err := tx.QueryRowContext(ctx, `
		SELECT name, remote_url, username, password_encrypted, sovereignty, last_sync, created_at, updated_at
		FROM federation_peers WHERE name = ?
	`, name).Scan(
		&row.Peer.Name, &row.Peer.RemoteURL, &username, &row.EncryptedPwd,
		&row.Peer.Sovereignty, &lastSync, &row.Peer.CreatedAt, &row.Peer.UpdatedAt,
	)

	if err == sql.ErrNoRows {
		return nil, fmt.Errorf("%w: federation peer %s", storage.ErrNotFound, name)
	}
	if err != nil {
		return nil, fmt.Errorf("get federation peer: %w", err)
	}

	if username.Valid {
		row.Peer.Username = username.String
	}
	if lastSync.Valid {
		row.Peer.LastSync = &lastSync.Time
	}

	return &row, nil
}

// ListFederationPeersInTx returns all configured federation peer rows.
func ListFederationPeersInTx(ctx context.Context, tx *sql.Tx) ([]*FederationPeerRow, error) {
	rows, err := tx.QueryContext(ctx, `
		SELECT name, remote_url, username, password_encrypted, sovereignty, last_sync, created_at, updated_at
		FROM federation_peers ORDER BY name
	`)

View on GitHub (pinned to 71377f2769)