fatedier/frp · error
client registry unavailable
Error message
client registry unavailable
What it means
The v2 API endpoint /api/v2/users aggregates clients by user via clientRegistry.List(); if the controller was built without a ClientRegistry the nil check fails and the endpoint errors out before pagination results are built.
Source
Thrown at server/http/controller_v2.go:114
return nil, err
}
cleared, total := mem.StatsCollector.PruneOfflineProxies()
return model.V2SystemPruneResp{
Type: pruneType,
Cleared: cleared,
Total: total,
}, nil
}
// /api/v2/users
func (c *Controller) APIV2UserList(ctx *httppkg.Context) (any, error) {
page, pageSize, err := parseV2PageParams(ctx)
if err != nil {
return nil, err
}
if c.clientRegistry == nil {
return nil, fmt.Errorf("client registry unavailable")
}
userStats := make(map[string]*model.V2UserResp)
for _, info := range c.clientRegistry.List() {
item := getOrCreateV2User(userStats, info.User)
item.ClientCount++
}
for _, proxyInfo := range c.listV2ProxyStats("") {
item := getOrCreateV2User(userStats, proxyInfo.User)
item.ProxyCount++
}
q := strings.ToLower(ctx.Query("q"))
items := make([]model.V2UserResp, 0, len(userStats))
for _, item := range userStats {
if q != "" && !strings.Contains(strings.ToLower(item.User), q) {
continue
}View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Wire the ClientRegistry into the Controller used for v2 routes.
- If a registry-less deployment is intentional, disable the v2 API routes.
- Add constructor functions (rather than struct literals) so controllers cannot be built half-initialized.
Example fix
// before
c := &Controller{} // v2 routes registered, registry nil
// after
c := NewController(clientRegistry, proxyManager) Defensive patterns
Strategy: validation
Validate before calling
if controller.ClientRegistry() == nil {
return errors.New("v2 user API unavailable without registry")
} Try / catch
// map to 503 and alert on occurrence — it signals a wiring regression, not user error
Prevention
- Register v2 routes only when a registry exists.
- Keep a single bootstrap path for controller construction.
When it happens
Trigger: A GET /api/v2/users request reaches a Controller whose clientRegistry field is nil — custom embedding, tests, or a broken bootstrap — after parseV2PageParams succeeds; the nil guard fires before any aggregation.
Common situations: Custom builds or embeddings of frps that register v2 routes but skip registry wiring; startup refactor dropping the registry argument; test controllers with partial fields.
Related errors
- serverHello.Error
- missing v2 crypto negotiation
- exec configuration is required when type is 'exec'
- file path cannot be empty
- exec command cannot be empty
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/92963c22e721c328.
Report an issue: GitHub.