{"record":{"id":"091b98b150ce482e","repo":"gastownhall/beads","slug":"failed-to-scan-federation-peer-w","errorCode":null,"errorMessage":"failed to scan federation peer: %w","messagePattern":"failed to scan federation peer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/credentials.go","lineNumber":382,"sourceCode":"func (s *DoltStore) ListFederationPeers(ctx context.Context) ([]*storage.FederationPeer, error) {\n\trows, err := s.queryContext(ctx, `\n\t\tSELECT name, remote_url, username, password_encrypted, sovereignty, last_sync, created_at, updated_at\n\t\tFROM federation_peers ORDER BY name\n\t`)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to list federation peers: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tvar peers []*storage.FederationPeer\n\tfor rows.Next() {\n\t\tvar peer storage.FederationPeer\n\t\tvar encryptedPwd []byte\n\t\tvar lastSync sql.NullTime\n\t\tvar username sql.NullString\n\n\t\tif err := rows.Scan(&peer.Name, &peer.RemoteURL, &username, &encryptedPwd, &peer.Sovereignty, &lastSync, &peer.CreatedAt, &peer.UpdatedAt); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to scan federation peer: %w\", err)\n\t\t}\n\n\t\tif username.Valid {\n\t\t\tpeer.Username = username.String\n\t\t}\n\t\tif lastSync.Valid {\n\t\t\tpeer.LastSync = &lastSync.Time\n\t\t}\n\n\t\t// Decrypt password\n\t\tif len(encryptedPwd) > 0 {\n\t\t\tif err := s.ensureCredentialKey(ctx); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to initialize credential key: %w\", err)\n\t\t\t}\n\t\t\tpeer.Password, err = s.decryptPassword(encryptedPwd)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to decrypt password: %w\", err)\n\t\t\t}","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/credentials.go#L364-L400","documentation":"ListFederationPeers scans each row into a FederationPeer with a fixed column list (name, remote_url, username, password_encrypted, sovereignty, last_sync, created_at, updated_at). This error means rows.Scan failed — the row's data doesn't match the expected 8-column shape or types. The library throws it to surface schema/driver mismatches during iteration.","triggerScenarios":"The federation_peers table has a different column count or order than the SELECT expects (schema drift from a different beads version or manual ALTERs); a NOT-NULL column holds a value incompatible with the destination type; driver type-conversion failure on e.g. created_at.","commonSituations":"Upgrading or downgrading beads so the table schema no longer matches the compiled queries; a hand-edited or partially migrated Dolt database; restoring rows from an export with reordered columns.","solutions":["Run bd's schema migration/init to bring federation_peers to the current shape.","Compare the table schema (SHOW CREATE TABLE federation_peers) against the 8 columns in the SELECT at credentials.go:366; add missing columns or fix types.","If rows came from a manual import, re-import through AddFederationPeer instead.","Check for a version mismatch between the bd binary and the database created by another version; align versions."],"exampleFix":"// before: table missing last_sync column from old schema\nerr := rows.Scan(&peer.Name, &peer.RemoteURL, &username, &encryptedPwd, &peer.Sovereignty, &lastSync, &peer.CreatedAt, &peer.UpdatedAt) // scan error\n// after: migrate schema so all 8 columns exist with compatible types\nALTER TABLE federation_peers ADD COLUMN last_sync DATETIME NULL;","handlingStrategy":"validation","validationCode":"// verify expected columns before listing\nrows, err := db.QueryContext(ctx, \"SHOW COLUMNS FROM federation_peers\")\n// count columns; expect 8: name, remote_url, username, password_encrypted, sovereignty, last_sync, created_at, updated_at","typeGuard":null,"tryCatchPattern":"peers, err := store.ListFederationPeers(ctx)\nvar scanErr bool\nif err != nil && strings.Contains(err.Error(), \"failed to scan federation peer\") {\n    scanErr = true // schema drift — run migrations\n}","preventionTips":["Run schema migrations after upgrading beads","Never hand-edit or ALTER the federation_peers table","Import peer rows via AddFederationPeer, not raw SQL inserts","Use one beads version against a given database"],"tags":["database","sql","schema","scan","federation"],"backgroundTag":"row-scan-type-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}