{"record":{"id":"1eb64a9cc05c8832","repo":"gastownhall/beads","slug":"w-federation-peer-s","errorCode":null,"errorMessage":"%w: federation peer %s","messagePattern":"%w: federation peer (.+?)","errorType":"exception","errorClass":"storage.ErrNotFound","httpStatus":null,"severity":"warning","filePath":"internal/storage/dolt/credentials.go","lineNumber":336,"sourceCode":"\n\treturn nil\n}\n\n// GetFederationPeer retrieves a federation peer by name.\n// Returns storage.ErrNotFound (wrapped) if the peer does not exist.\nfunc (s *DoltStore) GetFederationPeer(ctx context.Context, name string) (*storage.FederationPeer, error) {\n\tvar peer storage.FederationPeer\n\tvar encryptedPwd []byte\n\tvar lastSync sql.NullTime\n\tvar username sql.NullString\n\n\terr := s.db.QueryRowContext(ctx, `\n\t\tSELECT name, remote_url, username, password_encrypted, sovereignty, last_sync, created_at, updated_at\n\t\tFROM federation_peers WHERE name = ?\n\t`, name).Scan(&peer.Name, &peer.RemoteURL, &username, &encryptedPwd, &peer.Sovereignty, &lastSync, &peer.CreatedAt, &peer.UpdatedAt)\n\n\tif err == sql.ErrNoRows {\n\t\treturn nil, fmt.Errorf(\"%w: federation peer %s\", storage.ErrNotFound, name)\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get federation peer: %w\", err)\n\t}\n\n\tif username.Valid {\n\t\tpeer.Username = username.String\n\t}\n\tif lastSync.Valid {\n\t\tpeer.LastSync = &lastSync.Time\n\t}\n\n\t// Decrypt password\n\tif len(encryptedPwd) > 0 {\n\t\tif err := s.ensureCredentialKey(ctx); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to initialize credential key: %w\", err)\n\t\t}\n\t\tpeer.Password, err = s.decryptPassword(encryptedPwd)","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/credentials.go#L318-L354","documentation":"GetFederationPeer wraps storage.ErrNotFound when the query for the named peer returns sql.ErrNoRows. This is the library's sentinel for 'peer not registered' — callers should use errors.Is to detect it. It is an expected condition, not corruption: the peer name simply has no row in federation_peers.","triggerScenarios":"Calling GetFederationPeer (directly or via withPeerCredentials during push/pull) with a name that was never added via AddFederationPeer, was removed via RemoveFederationPeer, or is misspelled/differently-cased.","commonSituations":"Typos in `bd federation sync <peer>` style invocations; peers removed on another machine (credentials are local, not synced via refs/dolt/data for this table's absence in that flow); case-sensitive name mismatch ('Team-A' vs 'team-a').","solutions":["Use errors.Is(err, storage.ErrNotFound) to branch on this condition rather than string matching.","List configured peers (ListFederationPeers) to see the exact registered names.","Add the missing peer with AddFederationPeer if it should exist.","Check name spelling and case — lookup is exact-match SQL."],"exampleFix":"// before\npeer, err := store.GetFederationPeer(ctx, name)\nif err != nil { return err }\n// after\npeer, err := store.GetFederationPeer(ctx, name)\nif errors.Is(err, storage.ErrNotFound) {\n    return fmt.Errorf(\"peer %q not configured; run: bd federation add-peer %s <url>\", name, name)\n}\nif err != nil { return err }","handlingStrategy":"try-catch","validationCode":"peers, _ := store.ListFederationPeers(ctx)\nfor _, p := range peers { if p.Name == name { /* exists */ } }","typeGuard":"func isPeerNotFound(err error) bool { return errors.Is(err, storage.ErrNotFound) }","tryCatchPattern":"peer, err := store.GetFederationPeer(ctx, name)\nif isPeerNotFound(err) {\n    return fmt.Errorf(\"peer %q not configured; add it with AddFederationPeer\", name)\n}\nif err != nil { return err }","preventionTips":["Use errors.Is(err, storage.ErrNotFound), never string matching","Confirm exact name spelling/case via ListFederationPeers","Re-add peers on fresh clones — credentials table is workspace-local"],"tags":["go","not-found","federation","sentinel-error"],"backgroundTag":"peer-not-found","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}