{"record":{"id":"082864498e07f7c8","repo":"router-for-me/CLIProxyAPI","slug":"plugin-executor-s-received-nil-http-request","errorCode":null,"errorMessage":"plugin executor %s received nil HTTP request","messagePattern":"plugin executor (.+?) received nil HTTP request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/pluginhost/adapters_executors.go","lineNumber":793,"sourceCode":"\t\treturn coreexecutor.Response{}, errPrepare\n\t}\n\tpluginResp, errCountTokens := a.executor.CountTokens(ctx, buildExecutorRequest(a.host, a.provider, auth, prepared.req, prepared.opts))\n\tif errCountTokens != nil {\n\t\treturn coreexecutor.Response{}, errCountTokens\n\t}\n\treturn coreexecutor.Response{\n\t\tPayload:  a.translateExecutorResponse(ctx, prepared, pluginResp.Payload, false, nil),\n\t\tMetadata: cloneAnyMap(pluginResp.Metadata),\n\t\tHeaders:  cloneHeader(pluginResp.Headers),\n\t}, nil\n}\n\nfunc (a *executorAdapter) HttpRequest(ctx context.Context, auth *coreauth.Auth, req *http.Request) (resp *http.Response, err error) {\n\tif a == nil || a.executor == nil || a.host.isPluginFused(a.pluginID) || !a.host.pluginIdentityCurrent(a.pluginID, a.path, a.version) {\n\t\treturn nil, fmt.Errorf(\"plugin executor %s is unavailable\", a.Identifier())\n\t}\n\tif req == nil {\n\t\treturn nil, fmt.Errorf(\"plugin executor %s received nil HTTP request\", a.Identifier())\n\t}\n\tdefer func() {\n\t\tif recovered := recover(); recovered != nil {\n\t\t\ta.host.fusePlugin(a.pluginID, \"Executor.HttpRequest\", recovered)\n\t\t\tresp = nil\n\t\t\terr = fmt.Errorf(\"plugin executor %s http request panic: %v\", a.Identifier(), recovered)\n\t\t}\n\t}()\n\tbody, errReadAll := readAndRestoreRequestBody(req)\n\tif errReadAll != nil {\n\t\treturn nil, fmt.Errorf(\"read plugin http request body: %w\", errReadAll)\n\t}\n\tpluginResp, errHTTPRequest := a.executor.HttpRequest(ctx, pluginapi.ExecutorHTTPRequest{\n\t\tAuthID:       authID(auth),\n\t\tAuthProvider: authProvider(auth),\n\t\tMethod:       req.Method,\n\t\tURL:          req.URL.String(),\n\t\tHeaders:      cloneHeader(req.Header),","sourceCodeStart":775,"sourceCodeEnd":811,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/adapters_executors.go#L775-L811","documentation":"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.","triggerScenarios":"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.","commonSituations":"Wrapper/proxy code that constructs requests conditionally and forwards nil on failure; refactors that drop a nil check; unit tests with nil literals.","solutions":["Audit the call site of HttpRequest and check the request for nil before calling","Fix the upstream code that produced a nil request (e.g. http.NewRequest error ignored) and propagate that error instead","Add a unit test covering the nil-request path to lock in the guard"],"exampleFix":"// before\nresp, err := adapter.HttpRequest(ctx, auth, req) // req may be nil\n\n// after\nif req == nil {\n    return nil, errors.New(\"inbound request is nil\")\n}\nresp, err := adapter.HttpRequest(ctx, auth, req)","handlingStrategy":"validation","validationCode":"// Before calling the adapter:\nif req == nil {\n    return nil, errors.New(\"inbound request is nil\")\n}\nresp, err := adapter.HttpRequest(ctx, auth, req)","typeGuard":"func isHTTPRequestReady(req *http.Request) bool {\n    return req != nil && req.URL != nil && req.Method != \"\"\n}","tryCatchPattern":null,"preventionTips":["Never ignore errors from http.NewRequest — propagate them instead of forwarding nil","Lint wrapper/proxy layers for nil-request forwarding","Unit-test the nil-request path"],"tags":["plugin","nil-check","http","programming-error"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}