{"record":{"id":"d916f79371630b19","repo":"BerriAI/litellm","slug":"failed-to-sign-request-with-provided-oci-signer","errorCode":null,"errorMessage":"Failed to sign request with provided oci_signer: {e}. The signer must implement the OCI SDK Signer interface with a do_request_sign(request, enforce_content_headers=True) method. See: https://docs.oracle.com/en-us/iaas/tools/python/latest/api/signing.html","messagePattern":"Failed to sign request with provided oci_signer: (.+?)\\. The signer must implement the OCI SDK Signer interface with a do_request_sign\\(request, enforce_content_headers=True\\) method\\. See: https://docs\\.oracle\\.com/en-us/iaas/tools/python/latest/api/signing\\.html","errorType":"exception","errorClass":"OCIError","httpStatus":500,"severity":"error","filePath":"litellm/llms/oci/common_utils.py","lineNumber":232,"sourceCode":"    body: Final = json.dumps(request_data).encode(\"utf-8\")\n    method: Final = str(optional_params.get(\"method\", \"POST\")).upper()\n\n    if method not in {\"POST\", \"GET\", \"PUT\", \"DELETE\", \"PATCH\"}:\n        raise ValueError(f\"Unsupported HTTP method: {method}\")\n\n    prepared_headers: Final = {**headers}\n    prepared_headers.setdefault(\"content-type\", \"application/json\")\n    prepared_headers.setdefault(\"content-length\", str(len(body)))\n\n    request_wrapper: Final = OCIRequestWrapper(method=method, url=api_base, headers=prepared_headers, body=body)\n\n    if oci_signer is None:\n        raise ValueError(\"oci_signer cannot be None when calling sign_with_oci_signer\")\n\n    try:\n        oci_signer.do_request_sign(request_wrapper, enforce_content_headers=True)\n    except Exception as e:\n        raise OCIError(\n            status_code=500,\n            message=(\n                f\"Failed to sign request with provided oci_signer: {e}. \"\n                \"The signer must implement the OCI SDK Signer interface with a \"\n                \"do_request_sign(request, enforce_content_headers=True) method. \"\n                \"See: https://docs.oracle.com/en-us/iaas/tools/python/latest/api/signing.html\"\n            ),\n        ) from e\n\n    headers.update(request_wrapper.headers)\n    return headers, body\n\n\ndef sign_with_manual_credentials(\n    headers: dict,\n    optional_params: dict,\n    request_data: dict,\n    api_base: str,","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/oci/common_utils.py#L214-L250","documentation":"When an oci_signer object is supplied, litellm calls signer.do_request_sign(request, enforce_content_headers=True) inside a broad except Exception and rewraps any failure as OCIError(500) explaining the expected OCI SDK Signer interface. It fires when the provided object does not behave like an OCI SDK Signer or rejects the request wrapper.","triggerScenarios":"Passing a plain function, a mock, a dataclass, or an object from an incompatible oci SDK version whose do_request_sign has a different signature; a signer whose credentials are incomplete so signing itself throws; a signer subclass overriding do_request_sign with extra required kwargs.","commonSituations":"Users constructing signers manually (security_token_signer, instance_principals_signer) across oci SDK versions; test doubles replacing the signer; copy-pasted code building oci.signer.Signer(...) with tenancy/user/fingerprint/key_file misordered, causing an internal exception during signing.","solutions":["Build the signer exactly as the OCI SDK documents: oci.signer.Signer(tenancy, user, fingerprint, private_key_file_path, ...).","Upgrade/pin the oci package to a version whose Signer interface matches (do_request_sign(request, enforce_content_headers=True)).","In tests, mock at the HTTP layer instead of passing a fake signer into production code paths.","Check the embedded original exception text ({e}) — it names the actual attribute/signature mismatch."],"exampleFix":"# before\noptional_params[\"oci_signer\"] = lambda req: None  # OCIError(500)\n\n# after\nimport oci\noptional_params[\"oci_signer\"] = oci.signer.Signer(\n    tenancy=os.environ[\"OCI_TENANCY\"],\n    user=os.environ[\"OCI_USER\"],\n    fingerprint=os.environ[\"OCI_FINGERPRINT\"],\n    private_key_file_path=os.environ[\"OCI_KEY_FILE\"],\n)","handlingStrategy":"try-catch","validationCode":"signer = optional_params.get(\"oci_signer\")\nassert signer is not None and callable(getattr(signer, \"do_request_sign\", None)), \\\n    \"oci_signer must implement do_request_sign(request, enforce_content_headers=True)\"","typeGuard":"from typing import Any, Protocol\n\nclass OCISignerLike(Protocol):\n    def do_request_sign(self, request: Any, enforce_content_headers: bool = ...) -> None: ...\n\ndef is_valid_oci_signer(obj: Any) -> bool:\n    return callable(getattr(obj, \"do_request_sign\", None))","tryCatchPattern":"from litellm.llms.oci.common_utils import OCIError\ntry:\n    litellm.completion(model=\"oci/...\", messages=m)\nexcept OCIError as e:\n    if \"Failed to sign request with provided oci_signer\" in str(e):\n        raise ConfigError(\"oci_signer is not an OCI SDK Signer — rebuild with oci.signer.Signer(...)\") from e\n    raise","preventionTips":["Construct signers only via the official oci SDK (oci.signer.Signer / instance_principals_signer).","Pin the oci package version and test the signer against the real endpoint in CI.","Never substitute mocks or lambdas for the signer in production paths."],"tags":["oci","signing","sdk","interface-mismatch"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}