geektutu/7days-golang · error
RegisterPeerPicker called more than once
Error message
RegisterPeerPicker called more than once
What it means
Same as error 95, in the day6-single-flight version: RegisterPeers panics with "RegisterPeerPicker called more than once" when g.peers is already set. Peer configuration is one-shot per Group to prevent live replacement of the peer-selection topology.
Source
Thrown at gee-cache/day6-single-flight/geecache/geecache.go:82
// Get value for a key from cache
func (g *Group) Get(key string) (ByteView, error) {
if key == "" {
return ByteView{}, fmt.Errorf("key is required")
}
if v, ok := g.mainCache.get(key); ok {
log.Println("[GeeCache] hit")
return v, nil
}
return g.load(key)
}
// RegisterPeers registers a PeerPicker for choosing remote peer
func (g *Group) RegisterPeers(peers PeerPicker) {
if g.peers != nil {
panic("RegisterPeerPicker called more than once")
}
g.peers = peers
}
func (g *Group) load(key string) (value ByteView, err error) {
// each key is only fetched once (either locally or remotely)
// regardless of the number of concurrent callers.
viewi, err := g.loader.Do(key, func() (interface{}, error) {
if g.peers != nil {
if peer, ok := g.peers.PickPeer(key); ok {
if value, err = g.getFromPeer(peer, key); err == nil {
return value, nil
}
log.Println("[GeeCache] Failed to get from peer", err)
}
}
return g.getLocally(key)View on GitHub (pinned to cf36443821)
Solutions
- Register peers once, immediately after NewGroup
- Use sync.Once or a nil-check guard around registration
- Recreate the Group when peer configuration changes
Example fix
// before
var once sync.Once
func setup(g *geecache.Group, p geecache.PeerPicker) {
g.RegisterPeers(p) // called every time setup runs -> panic
}
// after
var once sync.Once
func setup(g *geecache.Group, p geecache.PeerPicker) {
once.Do(func() { g.RegisterPeers(p) })
} Defensive patterns
Strategy: validation
Validate before calling
var registerOnce sync.Once
func initPeers(g *geecache.Group, p geecache.PeerPicker) {
registerOnce.Do(func() { g.RegisterPeers(p) })
} Try / catch
defer func() {
if r := recover(); r == "RegisterPeerPicker called more than once" {
log.Println("RegisterPeers ignored: already registered")
}
}()
g.RegisterPeers(peers) Prevention
- One registration site per binary, wrapped in sync.Once
- On peer changes, construct a new Group rather than re-registering
- Guard against retried init paths calling setup twice
When it happens
Trigger: A second RegisterPeers call on the same Group — duplicate startup code, config reload re-registering peers, or tests reusing a Group instance across cases.
Common situations: Server restart logic that re-runs setup without recreating the Group; two packages each calling RegisterPeers on a shared group; retried init after a partial failure.
Related errors
- RegisterPeerPicker called more than once
- RegisterPeerPicker called more than once
- nil Getter
- nil Getter
- nil Getter
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/4e35e9da16de8113.
Report an issue: GitHub.