{"record":{"id":"456e78a339489189","repo":"can1357/oh-my-pi","slug":"no-codex-web-search-model-is-configured","errorCode":null,"errorMessage":"No Codex web search model is configured.","messagePattern":"No Codex web search model is configured\\.","errorType":"exception","errorClass":"SearchProviderError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/web/search/providers/codex.ts","lineNumber":741,"sourceCode":"\n/**\n * Executes a web search using OpenAI Codex's built-in web search tool.\n *\n * Default-model behavior:\n * - If `PI_CODEX_WEB_SEARCH_MODEL` is set, use it exactly once and surface any\n *   upstream error verbatim.\n * - Otherwise prefer ChatGPT-account-safe bundled defaults (GPT-5.6 Luna,\n *   Terra, Sol, GPT-5.5, …) and retry the next candidate only when Codex\n *   returns the known 400 \"model is not supported\" family. This avoids\n *   selecting `gpt-5-codex-mini` first on ChatGPT accounts, which OpenAI\n *   rejects.\n */\nexport async function searchCodex(params: SearchParams): Promise<SearchResponse> {\n\tconst configuredModel = getConfiguredModel();\n\tconst modelCandidates = configuredModel ? [configuredModel] : getDefaultModelCandidates();\n\tconst firstCandidate = modelCandidates[0];\n\tif (!firstCandidate) {\n\t\tthrow new SearchProviderError(\"codex\", \"No Codex web search model is configured.\");\n\t}\n\tconst transport = resolveCodexSearchTransport(params.modelRegistry, firstCandidate.modelId);\n\t// The ChatGPT-backend Codex endpoint speaks the undocumented codex-rs\n\t// request shape (responses-lite moves tools into an `additional_tools`\n\t// developer item), so the documented `web_search.filters.allowed_domains`\n\t// parameter cannot be assumed to survive it. Instead, re-emit directive\n\t// queries with the full Google-style operator syntax — the backing index\n\t// parses the classic operator set — and leave directive-free queries\n\t// byte-identical.\n\tconst parsed = params.parsedQuery ?? parseSearchQuery(params.query);\n\tconst query = parsed.hasDirectives ? formatQuery(parsed, GOOGLE_QUERY_SYNTAX) : params.query;\n\n\tlet result: CodexSearchResult;\n\tif (transport.customEndpoint) {\n\t\t// ModelRegistry resolves command-backed provider keys before consulting\n\t\t// its AuthStorage, so a lower-priority OAuth origin is irrelevant when\n\t\t// that command source is configured.\n\t\tconst credentialSource = params.modelRegistry?.authStorage ?? params.authStorage;","sourceCodeStart":723,"sourceCodeEnd":759,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/web/search/providers/codex.ts#L723-L759","documentation":"searchCodex resolves its model list from PI_CODEX_WEB_SEARCH_MODEL or the bundled default candidates. If both are absent — meaning the defaults list is empty and nothing is configured — it throws a SearchProviderError before any network call. This is a configuration-level guard ensuring the provider never sends a request without a model id.","triggerScenarios":"PI_CODEX_WEB_SEARCH_MODEL is set to an empty/blank value (getConfiguredModel returns undefined) AND getDefaultModelCandidates() returns an empty array — no first candidate exists.","commonSituations":"Environment variable exported as empty string; a trimmed-down build or test fixture without bundled default model candidates; misreading of config precedence so users believe a model is configured when it is not.","solutions":["Set PI_CODEX_WEB_SEARCH_MODEL to a valid Codex web-search-capable model id (e.g. gpt-5.6).","Unset the empty PI_CODEX_WEB_SEARCH_MODEL variable so bundled defaults are used.","Upgrade the package if your build is missing bundled default model candidates.","Configure a different search provider if Codex models are unavailable to your account."],"exampleFix":"// before\nexport PI_CODEX_WEB_SEARCH_MODEL=   # empty -> not configured\n// after\nexport PI_CODEX_WEB_SEARCH_MODEL=gpt-5.6","handlingStrategy":"validation","validationCode":"const model = getConfiguredModel();\nif (!model && getDefaultModelCandidates().length === 0) {\n  throw new Error(\"Set PI_CODEX_WEB_SEARCH_MODEL to a web-search-capable model id\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await searchCodex(params);\n} catch (e) {\n  if (e instanceof SearchProviderError && e.message.includes(\"No Codex web search model\")) {\n    return searchWithProvider(\"tavily\", params);\n  }\n  throw e;\n}","preventionTips":["Never export PI_CODEX_WEB_SEARCH_MODEL as an empty string; unset it instead to use bundled defaults.","Pin a known-good model id in deployment config.","Check model availability at startup rather than at first search."],"tags":["configuration","environment-variable","codex","search-provider"],"backgroundTag":"missing-env-var","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}