BerriAI/litellm · error · OCIError
{e.response.text}
Error message
{e.response.text} What it means
Raised by OCIBaseTransformation.get_sync_custom_stream_wrapper when the synchronous streaming POST to the OCI Generative AI inference endpoint fails with an HTTP error status. The response body text from OCI is wrapped in an OCIError (a BaseLLMException subclass) carrying the upstream status code, so LiteLLM's standard exception mapping/logging can surface it.
Source
Thrown at litellm/llms/oci/chat/transformation.py:658
messages: list,
client: HTTPHandler | AsyncHTTPHandler | None = None,
json_mode: bool | None = None,
signed_json_body: bytes | None = None,
) -> "OCIStreamWrapper":
if client is None or isinstance(client, AsyncHTTPHandler):
client = _get_httpx_client(params={})
try:
response: Final = client.post(
api_base,
headers=headers,
data=(signed_json_body if signed_json_body is not None else json.dumps(data)),
stream=True,
logging_obj=logging_obj,
timeout=STREAMING_TIMEOUT,
)
except httpx.HTTPStatusError as e:
raise OCIError(status_code=e.response.status_code, message=e.response.text)
if response.status_code != 200:
raise OCIError(status_code=response.status_code, message=response.text)
return OCIStreamWrapper(
completion_stream=_iter_sse_events(response.iter_text()),
model=model,
custom_llm_provider=custom_llm_provider,
logging_obj=logging_obj,
)
@track_llm_api_timing()
async def get_async_custom_stream_wrapper(
self,
model: str,
custom_llm_provider: str,
logging_obj: LiteLLMLoggingObj,
api_base: str,View on GitHub (pinned to 6c2dcb801b)
Solutions
- Inspect the OCIError.status_code and message: 401/403 means signing credentials are wrong, 404 means model OCID or region is wrong, 429 means back off and retry.
- Verify the model string uses a full OCID (ocid1.generativeai.model...) or an OCI-supported shorthand and that the region in the URL matches where the model is hosted.
- Confirm oci_user/oci_fingerprint/oci_tenancy/oci_key (or env vars OCI_USER etc.) belong to the same tenancy that has access to the model.
- For 429/5xx, retry with exponential backoff (litellm's built-in retry policy or your own).
Example fix
# before
resp = litellm.completion(model="oci/cohere.command-r-plus", messages=msgs, stream=True)
# after — catch the mapped provider error
import litellm
from litellm.llms.oci.common_utils import OCIError
try:
resp = litellm.completion(model="oci/cohere.command-r-plus", messages=msgs, stream=True)
except OCIError as e:
if e.status_code == 429:
time.sleep(2 ** attempt)
else:
raise Defensive patterns
Strategy: try-catch
Validate before calling
import os
required = ("OCI_USER", "OCI_FINGERPRINT", "OCI_TENANCY")
missing = [v for v in required if not os.environ.get(v)]
assert not missing and (os.environ.get("OCI_KEY") or os.environ.get("OCI_KEY_FILE")), f"missing: {missing}" Type guard
from litellm.llms.oci.common_utils import OCIError
def is_oci_error(e: BaseException) -> bool:
return isinstance(e, OCIError) Try / catch
from litellm.llms.oci.common_utils import OCIError
try:
stream = litellm.completion(model="oci/...", messages=m, stream=True)
except OCIError as e:
if e.status_code in (429,) or (e.status_code or 0) >= 500:
backoff_and_retry()
else:
raise # 4xx = fix config/request, do not retry Prevention
- Validate OCI credentials and model OCID at startup with a 1-token dry-run call.
- Keep credentials in env vars set by the deployment, not hardcoded defaults.
- Retry only 429/5xx; treat 4xx as configuration bugs.
When it happens
Trigger: Calling litellm.completion(..., model='oci/...', stream=True) synchronously, where the signed POST to https://inference.generativeai.<region>.oci.oraclecloud.com returns a non-2xx or httpx raises HTTPStatusError: wrong model OCID, unauthorized signing (bad fingerprint/key), rate limiting (429), or a malformed request body rejected by the service.
Common situations: Typo'd model OCID; expired or mismatched RSA key fingerprint; region not entitled for the model; throttling under burst load; on-prem proxy returning 4xx. Note this except-branch is effectively dead code for plain client.post(stream=True) because httpx only raises HTTPStatusError after an explicit raise_for_status() call — non-200 statuses normally flow to the status_code check that raises the sibling error.
Related errors
- {response.text}
- Error from qdrant checking if /collections exist {collection
- DeepEval logging error: {e.response.text}
- OpenMeter logging error: {e.response.text}
- _body (masked response body)
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/e98734c0a38c1128.
Report an issue: GitHub.