router-for-me/CLIProxyAPI · error

management registrar panic: %v

Error message

management registrar panic: %v

What it means

The host calls plugin.RegisterManagement during plugin registration inside a deferred recover(). If the plugin's registrar code panics, the host catches it, fuses the plugin (isPluginFused will short-circuit all future calls for its lifetime), and returns this error instead of crashing the process. This is a plugin bug caught by the host's isolation layer.

Source

Thrown at internal/pluginhost/management.go:107

			}
		}
	}

	h.mu.Lock()
	h.managementRoutes = nextRoutes
	h.resourceRoutes = nextResources
	h.mu.Unlock()
}

func (h *Host) callManagementRegistrar(ctx context.Context, record capabilityRecord, plugin pluginapi.ManagementAPI) (resp pluginapi.ManagementRegistrationResponse, err error) {
	if h == nil || plugin == nil || h.isPluginFused(record.id) || !h.recordCurrent(record) {
		return pluginapi.ManagementRegistrationResponse{}, nil
	}
	defer func() {
		if recovered := recover(); recovered != nil {
			h.fusePlugin(record.id, "ManagementAPI.RegisterManagement", recovered)
			resp = pluginapi.ManagementRegistrationResponse{}
			err = fmt.Errorf("management registrar panic: %v", recovered)
		}
	}()
	return plugin.RegisterManagement(ctx, pluginapi.ManagementRegistrationRequest{
		Plugin:           record.meta,
		BasePath:         managementBasePath,
		ResourceBasePath: resourcePluginBasePath + "/" + record.id,
	})
}

func normalizeManagementRoute(item pluginapi.ManagementRoute) (string, string, bool) {
	if item.Handler == nil {
		return "", "", false
	}
	method := strings.ToUpper(strings.TrimSpace(item.Method))
	if method == "" {
		method = http.MethodGet
	}
	if strings.ContainsAny(method, " \t\r\n") {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Report/fix the panic in the plugin: the %v payload is the recovered panic value with stack context in plugin logs
  2. Until fixed, disable the plugin in config so registration never runs
  3. If you author the plugin, add defensive nil checks in RegisterManagement and register a recover() of your own
  4. After fixing, reload/restart so the fused plugin becomes callable again

Example fix

// before (plugin code)
func (p *Plugin) RegisterManagement(ctx context.Context, req pluginapi.ManagementRegistrationRequest) (pluginapi.ManagementRegistrationResponse, error) {
    p.routes["/x"] = route // panics if routes is nil map
    ...
}

// after
func (p *Plugin) RegisterManagement(ctx context.Context, req pluginapi.ManagementRegistrationRequest) (pluginapi.ManagementRegistrationResponse, error) {
    if p.routes == nil {
        p.routes = map[string]pluginapi.ManagementRoute{}
    }
    p.routes["/x"] = route
    ...
}
Defensive patterns

Strategy: try-catch

Try / catch

resp, err := h.callManagementRegistrar(ctx, record, plugin)
if err != nil {
    // plugin is now fused; registration for it will no-op
    log.WithError(err).WithField("plugin", record.id).Error("management registration failed; plugin disabled")
}

Prevention

When it happens

Trigger: A management-capable plugin panicking inside RegisterManagement (nil map write, nil deref, index out of range) while registering its management/resource routes.

Common situations: Third-party plugin with untested registration code paths; plugin assuming config fields are populated (e.g. iterating a nil route slice after bad config); plugin receiving an unexpected BasePath and panicking.

Related errors


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