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 {
			continue

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Ensure the management Handler is built via the standard constructor that injects the auth manager (check where Handler is assembled in internal/api)
  2. If embedding the SDK, pass the service's auth manager before registering management routes
  3. In tests, construct the handler with a real or fake auth manager instead of a zero-value Handler
  4. 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

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


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/354ede32204d9e80. Report an issue: GitHub.