router-for-me/CLIProxyAPI · warning

plugin executor %s received nil HTTP request

Error message

plugin executor %s received nil HTTP request

What it means

HttpRequest was called with a nil *http.Request. The adapter validates the pointer before touching req.Method/req.URL and returns this error instead of panicking. This is a caller-side programming error, not a plugin or environment problem.

Source

Thrown at internal/pluginhost/adapters_executors.go:793

		return coreexecutor.Response{}, errPrepare
	}
	pluginResp, errCountTokens := a.executor.CountTokens(ctx, buildExecutorRequest(a.host, a.provider, auth, prepared.req, prepared.opts))
	if errCountTokens != nil {
		return coreexecutor.Response{}, errCountTokens
	}
	return coreexecutor.Response{
		Payload:  a.translateExecutorResponse(ctx, prepared, pluginResp.Payload, false, nil),
		Metadata: cloneAnyMap(pluginResp.Metadata),
		Headers:  cloneHeader(pluginResp.Headers),
	}, nil
}

func (a *executorAdapter) HttpRequest(ctx context.Context, auth *coreauth.Auth, req *http.Request) (resp *http.Response, err error) {
	if a == nil || a.executor == nil || a.host.isPluginFused(a.pluginID) || !a.host.pluginIdentityCurrent(a.pluginID, a.path, a.version) {
		return nil, fmt.Errorf("plugin executor %s is unavailable", a.Identifier())
	}
	if req == nil {
		return nil, fmt.Errorf("plugin executor %s received nil HTTP request", a.Identifier())
	}
	defer func() {
		if recovered := recover(); recovered != nil {
			a.host.fusePlugin(a.pluginID, "Executor.HttpRequest", recovered)
			resp = nil
			err = fmt.Errorf("plugin executor %s http request panic: %v", a.Identifier(), recovered)
		}
	}()
	body, errReadAll := readAndRestoreRequestBody(req)
	if errReadAll != nil {
		return nil, fmt.Errorf("read plugin http request body: %w", errReadAll)
	}
	pluginResp, errHTTPRequest := a.executor.HttpRequest(ctx, pluginapi.ExecutorHTTPRequest{
		AuthID:       authID(auth),
		AuthProvider: authProvider(auth),
		Method:       req.Method,
		URL:          req.URL.String(),
		Headers:      cloneHeader(req.Header),

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Audit the call site of HttpRequest and check the request for nil before calling
  2. Fix the upstream code that produced a nil request (e.g. http.NewRequest error ignored) and propagate that error instead
  3. Add a unit test covering the nil-request path to lock in the guard

Example fix

// before
resp, err := adapter.HttpRequest(ctx, auth, req) // req may be nil

// after
if req == nil {
    return nil, errors.New("inbound request is nil")
}
resp, err := adapter.HttpRequest(ctx, auth, req)
Defensive patterns

Strategy: validation

Validate before calling

// Before calling the adapter:
if req == nil {
    return nil, errors.New("inbound request is nil")
}
resp, err := adapter.HttpRequest(ctx, auth, req)

Type guard

func isHTTPRequestReady(req *http.Request) bool {
    return req != nil && req.URL != nil && req.Method != ""
}

Prevention

When it happens

Trigger: Passing a nil *http.Request to executorAdapter.HttpRequest — e.g. a handler that returns nil on a malformed inbound request and forwards it without checking, or a test that passes nil.

Common situations: Wrapper/proxy code that constructs requests conditionally and forwards nil on failure; refactors that drop a nil check; unit tests with nil literals.

Related errors


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