{"record":{"id":"122b717af7e810dc","repo":"BerriAI/litellm","slug":"private-key-is-required-for-oci-authentication-pr","errorCode":null,"errorMessage":"Private key is required for OCI authentication. Provide either oci_key or oci_key_file.","messagePattern":"Private key is required for OCI authentication\\. Provide either oci_key or oci_key_file\\.","errorType":"exception","errorClass":"OCIError","httpStatus":400,"severity":"critical","filePath":"litellm/llms/oci/common_utils.py","lineNumber":325,"sourceCode":"            raise OCIError(\n                status_code=400,\n                message=(\n                    f\"oci_key must be a string containing the PEM private key content. \"\n                    f\"Got type: {type(oci_key).__name__}\"\n                ),\n            )\n        oci_key_content = oci_key.replace(\"\\\\n\", \"\\n\").replace(\"\\r\\n\", \"\\n\")\n\n    private_key: Final = (\n        load_private_key_from_str(oci_key_content)\n        if oci_key_content\n        else load_private_key_from_file(oci_key_file)\n        if oci_key_file\n        else None\n    )\n\n    if private_key is None:\n        raise OCIError(\n            status_code=400,\n            message=\"Private key is required for OCI authentication. Provide either oci_key or oci_key_file.\",\n        )\n\n    signature: Final = private_key.sign(\n        signing_string.encode(\"utf-8\"),\n        padding.PKCS1v15(),\n        hashes.SHA256(),\n    )\n    signature_b64: Final = base64.b64encode(signature).decode()\n\n    key_id: Final = f\"{oci_tenancy}/{oci_user}/{oci_fingerprint}\"\n    authorization: Final = (\n        'Signature version=\"1\",'\n        f'keyId=\"{key_id}\",'\n        'algorithm=\"rsa-sha256\",'\n        f'headers=\"{\" \".join(signed_header_names)}\",'\n        f'signature=\"{signature_b64}\"'","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/oci/common_utils.py#L307-L343","documentation":"After resolving the private key from oci_key or oci_key_file, sign_with_manual_credentials raises OCIError(400) if no key could be obtained. It differs from the 401 missing-credentials error: it specifically means the key sources were present-but-falsy (e.g. empty strings) or the caller reached this path with neither key field set.","triggerScenarios":"oci_key='' or oci_key_file='' (empty strings from unset env vars), or calling the signing helper directly without any key argument while user/fingerprint/tenancy happen to be set.","commonSituations":"os.environ.get('OCI_KEY', '') producing '' when the var is unset; Helm values defaulting key to empty string; partial config where the user copied only some fields from ~/.oci/config.","solutions":["Provide the PEM content via oci_key/OCI_KEY or a valid path via oci_key_file/OCI_KEY_FILE.","Use None-coalescing instead of empty defaults: os.environ.get('OCI_KEY') or os.environ.get('OCI_KEY_FILE').","Fail fast at startup if neither key source is configured.","Prefer OCI_KEY_FILE pointing at the same PEM used in ~/.oci/config to avoid duplication."],"exampleFix":"# before\nos.environ[\"OCI_KEY\"] = os.environ.get(\"OCI_KEY\", \"\")  # '' passes truthiness of presence, then 400\n\n# after\nif not (os.environ.get(\"OCI_KEY\") or os.environ.get(\"OCI_KEY_FILE\")):\n    raise RuntimeError(\"Configure OCI_KEY or OCI_KEY_FILE\")","handlingStrategy":"validation","validationCode":"import os\nkey = os.environ.get(\"OCI_KEY\") or None\nkey_file = os.environ.get(\"OCI_KEY_FILE\") or None\nassert key or (key_file and os.path.isfile(key_file)), \"Provide OCI_KEY or an existing OCI_KEY_FILE\"","typeGuard":null,"tryCatchPattern":"from litellm.llms.oci.common_utils import OCIError\ntry:\n    litellm.completion(model=\"oci/...\", messages=m)\nexcept OCIError as e:\n    if e.status_code == 400 and \"Private key is required\" in str(e):\n        raise ConfigError(\"set OCI_KEY (PEM content) or OCI_KEY_FILE (path)\") from e\n    raise","preventionTips":["Never default key env vars to empty strings; leave them unset and check for None.","Fail fast at startup if neither key source is present.","Mirror ~/.oci/config as the source of truth for key location."],"tags":["oci","authentication","credentials","validation"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}