gastownhall/beads · error
failed to iterate peers for migration: %w
Error message
failed to iterate peers for migration: %w
What it means
After scanning all federation_peers rows, migrateCredentialKeys checks rows.Err() to detect any error that terminated row iteration. This error wraps such an iteration failure — typically a dropped or timed-out database connection mid-scan, or a driver-level read error. It guarantees a broken migration is reported instead of silently re-encrypting only a prefix of the peer list.
Source
Thrown at internal/storage/dolt/credentials.go:178
var toMigrate []migrationEntry
for rows.Next() {
var name string
var encrypted []byte
if err := rows.Scan(&name, &encrypted); err != nil {
return fmt.Errorf("failed to scan peer for migration: %w", err)
}
// Decrypt with old key
plaintext, err := decryptWithKey(encrypted, oldKey)
if err != nil {
// Can't decrypt with old key — skip (may already use a different scheme)
continue
}
toMigrate = append(toMigrate, migrationEntry{name: name, plaintext: plaintext})
}
if err := rows.Err(); err != nil {
return fmt.Errorf("failed to iterate peers for migration: %w", err)
}
// Re-encrypt each password with the new key
for _, entry := range toMigrate {
encrypted, err := encryptWithKey(entry.plaintext, newKey)
if err != nil {
return fmt.Errorf("failed to re-encrypt password for peer %s: %w", entry.name, err)
}
if _, err := s.execContext(ctx, `
UPDATE federation_peers SET password_encrypted = ? WHERE name = ?
`, encrypted, entry.name); err != nil {
return fmt.Errorf("failed to update encrypted password for peer %s: %w", entry.name, err)
}
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Increase the context/command timeout or retry — migration re-runs on next open while no key file exists
- Verify connectivity to the Dolt server (ping/hosted instance health) and network stability
- Check server logs for aborted connections around the failure time
- Reduce peer-table contention: ensure no concurrent bd processes hold long transactions on federation_peers
Defensive patterns
Strategy: retry
Validate before calling
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() // give row iteration room to finish on slow links
Try / catch
if err := bdSync(); err != nil && strings.Contains(err.Error(), "failed to iterate peers for migration") {
return retryWithBackoff(bdSync, 3) // migration re-runs safely while no key file exists
} Prevention
- Use stable, low-latency connections to remote dolt-sql-server instances
- Set generous timeouts for bd operations over slow networks
- Avoid killing bd mid-startup while migration may be in flight
When it happens
Trigger: rows.Err() returns non-nil after the rows.Next() loop in migrateCredentialKeys: the SQL connection to Dolt dropped or the context was canceled/timed out while streaming rows, or the underlying driver hit an I/O error reading the result set.
Common situations: Slow or flaky connection to a remote dolt-sql-server timing out during migration on open; context deadline exceeded because migration ran during a slow startup with many peers; network interruption to a hosted Dolt instance.
Related errors
- failed to scan peer for migration: %w
- failed to update encrypted password for peer %s: %w
- search union with counts: %w
- db: RawSQL Query: rows: %w
- re-key id %s -> %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/8cb7ff8168d7b952.
Report an issue: GitHub.