{"record":{"id":"11529b3ba52c6ecd","repo":"assafelovic/gpt-researcher","slug":"failed-to-get-response-from-llm-provider-api","errorCode":null,"errorMessage":"Failed to get response from {llm_provider} API","messagePattern":"Failed to get response from (.+?) API","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"gpt_researcher/utils/llm.py","lineNumber":158,"sourceCode":"                continue\n            break\n\n        if cost_callback:\n            llm_costs = calculate_llm_cost(\n                llm_provider=llm_provider,\n                model=model,\n                input_content=str(messages),\n                output_content=response,\n                response_metadata=provider.last_response_metadata,\n                usage_metadata=provider.last_usage_metadata,\n                request_options=provider_kwargs,\n            )\n            cost_callback(llm_costs)\n\n        return response\n\n    logging.error(f\"Failed to get response from {llm_provider} API\")\n    raise RuntimeError(f\"Failed to get response from {llm_provider} API\") from last_exception\n\n\nasync def construct_subtopics(\n    task: str,\n    data: str,\n    config,\n    subtopics: list = [],\n    prompt_family: type[PromptFamily] | PromptFamily = PromptFamily,\n    **kwargs\n) -> list:\n    \"\"\"\n    Construct subtopics based on the given task and data.\n\n    Args:\n        task (str): The main task or topic.\n        data (str): Additional data for context.\n        config: Configuration settings.\n        subtopics (list, optional): Existing subtopics. Defaults to [].","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/assafelovic/gpt-researcher/blob/6f998577d547b1e54ec662dac63583aa11e3b84b/gpt_researcher/utils/llm.py#L140-L176","documentation":"After create_chat_completion exhausts its provider retry loop, it logs and raises RuntimeError chained from the last exception. This is the catch-all 'the LLM API never succeeded' error — the underlying cause (network, auth, quota, malformed request) is attached as __cause__ via `from last_exception`.","triggerScenarios":"Every attempt to call the LLM provider failed: invalid/expired API key (401), rate limit or quota exhausted (429), model name not found, network/DNS failure, or a provider SDK incompatibility — after all internal retries are spent, this RuntimeError surfaces to callers like generate_feedback or choose_agent.","commonSituations":"Expired OpenAI key, hitting org rate limits during long research runs, wrong model name after a provider deprecation, corporate proxy blocking api.openai.com, or mismatched langchain/langchain-openai versions after an upgrade.","solutions":["Inspect the chained exception: `except RuntimeError as e: print(e.__cause__)` to see the real HTTP error","Verify the API key (OPENAI_API_KEY or provider equivalent) and that it has quota/billing","Reduce request rate or add backoff; check provider status page","Pin/upgrade langchain + provider packages to versions compatible with your gpt-researcher release","Catch RuntimeError in your orchestration code and fall back to a cheaper provider/model"],"exampleFix":"# before\nresp = await create_chat_completion(...)  # RuntimeError: Failed to get response from openai API\n\n# after\ntry:\n    resp = await create_chat_completion(...)\nexcept RuntimeError as e:\n    logger.error('LLM failed: %s', e.__cause__)\n    resp = await create_chat_completion(..., llm_provider='ollama')  # fallback","handlingStrategy":"fallback","validationCode":"import os\nassert os.getenv('OPENAI_API_KEY'), 'Missing OPENAI_API_KEY — LLM calls will fail'","typeGuard":null,"tryCatchPattern":"try:\n    resp = await create_chat_completion(prompt, model)\nexcept RuntimeError as e:\n    logger.warning('LLM provider failed: %s', e.__cause__)\n    resp = await create_chat_completion(prompt, fallback_model)  # retry/fallback","preventionTips":["Always inspect e.__cause__ — the real HTTP error is chained there","Set up a secondary provider (e.g. ollama) as a fallback for long research runs","Implement exponential backoff around the whole research step, not just single calls","Monitor quota/rate-limit headers to back off before 429s exhaust retries"],"tags":["llm","api-failure","retry-exhausted","network","runtimeerror"],"backgroundTag":"llm-api-request-failed","analyzedSha":"6f998577d547b1e54ec662dac63583aa11e3b84b","analyzedAt":"2026-08-28T17:50:07.383Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}