{"record":{"id":"ef80c214934690f4","repo":"router-for-me/CLIProxyAPI","slug":"codex-alpha-search-api-key-base-url-unavailable","errorCode":null,"errorMessage":"Codex Alpha Search API key base URL unavailable","messagePattern":"Codex Alpha Search API key base URL unavailable","errorType":"http","errorClass":null,"httpStatus":503,"severity":"error","filePath":"internal/api/server_routes.go","lineNumber":391,"sourceCode":"\t\t\treturn\n\t\t}\n\t\tctx = attemptCtx\n\t\treleaseAttempt = release\n\t\tdefer releaseAttempt()\n\t}\n\tlogging.SetGinCPATraceID(c, selected.EnsureIndex())\n\n\tbaseHeaders := make(http.Header)\n\tbaseHeaders.Set(\"Content-Type\", \"application/json\")\n\tbaseHeaders.Set(\"Accept\", \"application/json\")\n\tbaseHeaders.Set(\"Originator\", \"codex_cli_rs\")\n\tfor _, name := range []string{\"Version\", \"User-Agent\", \"Session_id\", \"X-Client-Request-Id\"} {\n\t\tif value := strings.TrimSpace(c.GetHeader(name)); value != \"\" {\n\t\t\tbaseHeaders.Set(name, value)\n\t\t}\n\t}\n\n\terrMissingBaseURL := errors.New(\"Codex Alpha Search API key base URL unavailable\")\n\trouteModel := strings.TrimSpace(selectionModel)\n\tif routeModel == \"\" {\n\t\trouteModel = strings.TrimSpace(routing.Model)\n\t}\n\tperformRequest := func(current *auth.Auth) (*http.Response, error) {\n\t\theaders := baseHeaders.Clone()\n\t\tif accountID, ok := current.Metadata[\"account_id\"].(string); ok && strings.TrimSpace(accountID) != \"\" {\n\t\t\theaders.Set(\"Chatgpt-Account-Id\", accountID)\n\t\t}\n\t\tupstreamURL := \"https://chatgpt.com/backend-api/codex/alpha/search\"\n\t\trequestBody := upstreamRequestBody\n\t\t// API-key Alpha Search reuses normal credential-aware model resolution so\n\t\t// CPA routing prefixes and model aliases are not forwarded upstream.\n\t\tif current.AuthKind() == auth.AuthKindAPIKey {\n\t\t\tbaseURL := \"\"\n\t\t\tif current.Attributes != nil {\n\t\t\t\tbaseURL = strings.TrimSpace(current.Attributes[\"base_url\"])\n\t\t\t}","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/api/server_routes.go#L373-L409","documentation":"The host returns this when currentModelExecutor() yields nil, meaning no model executor was registered on the plugin host before the plugin invoked host.model.execute_stream. The executor is the host-side bridge into the core model pipeline; without it the callback cannot reach any model.","triggerScenarios":"A plugin calls host.model.execute_stream before the host has been given an executor via its SetModelExecutor-style wiring, or after the executor was cleared during host shutdown/reconfiguration.","commonSituations":"Unit tests that construct a bare Host without an executor; plugins that fire model calls during plugin load (before the core service registers the executor); host teardown racing an in-flight callback.","solutions":["Ensure the host is fully initialized and the model executor is registered before plugins are loaded or allowed to call host.model.execute_stream.","In tests, register a stub executor on the Host so currentModelExecutor() is non-nil.","In the plugin, defer host.model.execute_stream calls until after host startup completes (e.g. an init/ready hook), and handle the error without retry loops against a shutting-down host."],"exampleFix":"// test setup: give the host a model executor before plugins can stream\nhost := pluginhost.New(...)\nhost.SetModelExecutor(stubExecutor) // before LoadPlugins / plugin init\n\n// plugin side: fail soft when executor is not wired yet\nresp, err := host.Call(ctx, \"host.model.execute_stream\", raw)\nif err != nil && strings.Contains(err.Error(), \"executor is unavailable\") {\n    return fmt.Errorf(\"host not ready for model execution: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// plugin side: only call model callbacks once the host signaled readiness\nif !hostReady.Load() {\n    return errors.New(\"host model executor not ready\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := host.Call(ctx, \"host.model.execute_stream\", raw)\nif err != nil && strings.Contains(err.Error(), \"executor is unavailable\") {\n    // host wiring/lifecycle problem: surface it, do not retry blindly\n    return fmt.Errorf(\"host not ready for model execution: %w\", err)\n}","preventionTips":["Register the model executor on the Host before loading plugins.","Defer host.model.* calls until after host startup completes.","In tests, always inject a stub executor."],"tags":["pluginhost","lifecycle","executor"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}