router-for-me/CLIProxyAPI · error
core auth manager unavailable
Error message
core auth manager unavailable
What it means
patchPluginVirtualSourceStatus refuses to operate when h, h.authManager, or targetAuth is nil. The core auth manager is the runtime credential registry; without it the handler cannot enumerate or update the auths expanded from a plugin multi-auth source file, so toggling disabled state is aborted before touching disk.
Source
Thrown at internal/api/handlers/management/auth_files_fields.go:121
"excluded_pattern": configAPIKeyDisablePattern,
})
return
}
applyAuthDisabledState(targetAuth, *req.Disabled)
if _, err := h.authManager.Update(ctx, targetAuth); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to update auth: %v", err)})
return
}
c.JSON(http.StatusOK, gin.H{"status": "ok", "disabled": *req.Disabled})
}
// patchPluginVirtualSourceStatus toggles disabled on a plugin multi-auth source file and all
// runtime auths expanded from it. Virtual project children cannot be toggled independently.
func (h *Handler) patchPluginVirtualSourceStatus(ctx context.Context, targetAuth *coreauth.Auth, disabled bool) error {
if h == nil || h.authManager == nil || targetAuth == nil {
return fmt.Errorf("core auth manager unavailable")
}
sourcePath := strings.TrimSpace(authAttribute(targetAuth, coreauth.AttributeVirtualSource))
if sourcePath == "" {
sourcePath = strings.TrimSpace(authAttribute(targetAuth, "path"))
}
if sourcePath == "" {
return errPluginVirtualAuth
}
if errWrite := setSourceAuthFileDisabled(sourcePath, disabled); errWrite != nil {
if os.IsNotExist(errWrite) {
return errAuthFileNotFound
}
return fmt.Errorf("failed to update source auth file: %w", errWrite)
}
now := time.Now()
for _, auth := range h.authManager.List() {
if auth == nil {
continueView on GitHub (pinned to 78f0c4079e)
Solutions
- Ensure the management Handler is built via the standard constructor that injects the auth manager (check where Handler is assembled in internal/api)
- If embedding the SDK, pass the service's auth manager before registering management routes
- In tests, construct the handler with a real or fake auth manager instead of a zero-value Handler
- Retry the toggle after the server fully initializes (the manager is set during service startup)
Example fix
// before
h := &management.Handler{} // no auth manager
// after
h := management.NewHandler(service.AuthManager(), service.Config()) Defensive patterns
Strategy: type-guard
Validate before calling
if h == nil || h.authManager == nil {
return errors.New("management handler not wired: auth manager missing — check service init order")
} Type guard
func (h *Handler) ready() bool { return h != nil && h.authManager != nil } Prevention
- Construct handlers only via constructors that inject all dependencies
- Assert at startup that the auth manager is set before routes serve
- In tests, always inject a fake auth manager
When it happens
Trigger: A PATCH request to toggle a plugin virtual auth's disabled flag on a handler constructed without an injected auth manager — unit tests building Handler{} directly, or an initialization-order bug where management routes are registered before the auth manager is set on the handler.
Common situations: Embedding the SDK and wiring management routes manually while skipping the auth-manager dependency; refactors that add a new Handler constructor path without propagating the manager; test harnesses hitting management endpoints in isolation.
Related errors
- failed to read auth file: %w
- invalid auth file: %w
- token store unavailable
- core auth manager unavailable
- pluginhost: token store unavailable
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/354ede32204d9e80.
Report an issue: GitHub.