{"record":{"id":"b7e374e3b045b0a3","repo":"BerriAI/litellm","slug":"api-base-not-set-set-api-base-or-litellm-api-base","errorCode":null,"errorMessage":"api_base not set. Set api_base or litellm.api_base for custom endpoints","messagePattern":"api_base not set\\. Set api_base or litellm\\.api_base for custom endpoints","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/main.py","lineNumber":4678,"sourceCode":"\ndef _custom_api_first_output(resp: httpx.Response | None) -> str:\n    return resp.json()[\"data\"][0][\"output\"][0]\n\n\ndef _complete_custom(ctx: _CompletionDispatchContext) -> _CompletionDispatchResult:\n    api_base: Final = ctx.api_base\n    headers: Final = ctx.headers\n    kwargs: Final = ctx.kwargs\n    max_tokens: Final = ctx.max_tokens\n    messages: Final = ctx.messages\n    model: Final = ctx.model\n    model_response: Final = ctx.model_response\n    temperature: Final = ctx.temperature\n    top_p: Final = ctx.top_p\n\n    url: Final = litellm.api_base or api_base or \"\"\n    if url is None or url == \"\":\n        raise ValueError(\"api_base not set. Set api_base or litellm.api_base for custom endpoints\")\n\n    \"\"\"\n    assume input to custom LLM api bases follow this format:\n    resp = litellm.module_level_client.post(\n        api_base,\n        json={\n            'model': 'meta-llama/Llama-2-13b-hf', # model name\n            'params': {\n                'prompt': [\"The capital of France is P\"],\n                'max_tokens': 32,\n                'temperature': 0.7,\n                'top_p': 1.0,\n                'top_k': 40,\n            }\n        }\n    )\n\n    \"\"\"","sourceCodeStart":4660,"sourceCodeEnd":4696,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/main.py#L4660-L4696","documentation":"ValueError from the custom-endpoint text-completion path: it resolves url = litellm.api_base or api_base and raises when the result is None or ''. Custom (non-OpenAI) completion endpoints follow a documented POST {api_base} format, and without a URL there is nothing to POST to.","triggerScenarios":"text_completion / completion on a custom openai-compatible provider (e.g. model='text-completion-openai/<name>' or a custom handler) where neither the api_base argument nor litellm.api_base was set (note: environment fallbacks are not consulted on this path).","commonSituations":"Relying on OPENAI_API_BASE env var, which this custom path ignores; setting api_base on a different call than the one that dispatches; local LLM server (llama.cpp, vllm) moved ports and the global was never updated.","solutions":["Pass api_base='http://localhost:8000/v1' (your server URL) on the call","Or set litellm.api_base = 'http://localhost:8000/v1' globally before invoking","Do not rely on OPENAI_API_BASE/OPENAI_BASE_URL here -- this path reads only the arg and the litellm global","Double-check the value is a non-empty string (not None/'') after config loading"],"exampleFix":"# before\nresp = litellm.text_completion(model='text-completion-openai/llama-3', prompt='hi')  # ValueError\n\n# after\nresp = litellm.text_completion(model='text-completion-openai/llama-3', prompt='hi', api_base='http://localhost:8000/v1')","handlingStrategy":"validation","validationCode":"url = litellm.api_base or api_base\nif not url:\n    raise SystemExit('custom endpoint needs api_base or litellm.api_base')","typeGuard":"def custom_base_set(url: str | None) -> bool:\n    return isinstance(url, str) and bool(url.strip())","tryCatchPattern":"try:\n    resp = litellm.text_completion(model='text-completion-openai/llama-3', prompt='hi', api_base=base)\nexcept ValueError as e:\n    if 'api_base not set' in str(e):\n        raise RuntimeError('custom endpoint URL missing: set api_base (env vars are not read here)') from e\n    raise","preventionTips":["This path ignores OPENAI_API_BASE/OPENAI_BASE_URL -- always pass api_base or set litellm.api_base explicitly","Centralize your local-LLM base URL in one config constant reused by every call","After moving a local server, grep for the old host:port across config, not just env files","Assert the base URL is a non-empty http(s) string before dispatch in shared helper code"],"tags":["custom-endpoint","api-base","text-completion","litellm"],"backgroundTag":"missing-api-base","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}