BerriAI/litellm · critical · TypeError
The provided private key is not an RSA key, which is require
Error message
The provided private key is not an RSA key, which is required for OCI signing.
What it means
load_private_key_from_str loads the PEM private key and enforces that it is an RSA key, because OCI request signing uses RSA PKCS1v15 + SHA256. An EC/Ed25519 key parses fine but cannot produce a valid OCI signature, so it is rejected immediately with TypeError instead of producing cryptic 401s.
Source
Thrown at litellm/llms/oci/common_utils.py:123
def build_signature_string(method: str, path: str, headers: dict, signed_headers: list) -> str:
lines: Final = []
for header in signed_headers:
if header == "(request-target)":
value = f"{method.lower()} {path}"
else:
value = headers[header]
lines.append(f"{header}: {value}")
return "\n".join(lines)
def load_private_key_from_str(key_str: str) -> Any:
_require_cryptography()
key: Final = serialization.load_pem_private_key(
key_str.encode("utf-8"),
password=None,
)
if not isinstance(key, rsa.RSAPrivateKey):
raise TypeError("The provided private key is not an RSA key, which is required for OCI signing.")
return key
def load_private_key_from_file(file_path: str) -> Any:
"""Loads a private key from a file path."""
try:
with open(file_path, "r", encoding="utf-8") as f:
key_str: Final = f.read().strip()
except FileNotFoundError:
raise FileNotFoundError(f"Private key file not found: {file_path}")
except OSError as e:
raise OSError(f"Failed to read private key file '{file_path}': {e}") from e
if not key_str:
raise ValueError(f"Private key file is empty: {file_path}")
return load_private_key_from_str(key_str)
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Generate an RSA key: openssl genrsa -out oci_key.pem 2048 (or ssh-keygen -t RSA -b 2048 -m PEM).
- Upload the new public key in the OCI Console (Identity > Users > API Keys) and copy the new fingerprint into OCI_FINGERPRINT.
- Point oci_key_file / OCI_KEY_FILE at the RSA PEM file.
- Verify: openssl rsa -in oci_key.pem -check -noout succeeds only for RSA keys.
Example fix
# before (ed25519/EC key → TypeError) # key generated with: ssh-keygen -t ed25519 # after # openssl genrsa -out ~/.oci/oci_key.pem 2048 # upload public key in OCI Console, update fingerprint litellm.completion(model="oci/...", messages=m) # signs successfully
Defensive patterns
Strategy: validation
Validate before calling
from cryptography.hazmat.primitives import serialization key = serialization.load_pem_private_key(pem.encode(), password=None) from cryptography.hazmat.primitives.asymmetric import rsa assert isinstance(key, rsa.RSAPrivateKey), "OCI requires an RSA private key"
Type guard
from cryptography.hazmat.primitives.asymmetric import rsa
def is_rsa_key(key) -> bool:
return isinstance(key, rsa.RSAPrivateKey) Try / catch
try:
litellm.completion(model="oci/...", messages=m)
except TypeError as e:
if "not an RSA key" in str(e):
raise ConfigError("Regenerate key: openssl genrsa -out oci_key.pem 2048 and re-upload") from e
raise Prevention
- Standardize key generation: openssl genrsa -out oci_key.pem 2048.
- Re-verify the key type after any key rotation or provider migration.
- Add a startup check that the configured key parses as RSA.
When it happens
Trigger: The OCI_USER's API key was generated as ECDSA or Ed25519 instead of RSA-2048+, or the wrong key file (e.g. an SSH ed25519 key) was pointed at by OCI_KEY_FILE / oci_key_file.
Common situations: Developers reusing ~/.ssh/id_ed25519; OpenSSL defaults drifting to EC keys (openssl genpkey -algorithm EC); keys generated for a different cloud provider; copying an OCI config file whose key_file path points at an EC key generated later.
Related errors
- Missing required OCI credentials: oci_user, oci_fingerprint,
- Private key is required for OCI authentication. Provide eith
- Authentication failed. Check your BitBucket access token and
- Authentication failed. Check your GitLab token and auth_meth
- BedrockException Invalid Authentication - {error_str}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/e5b89946f0b4de07.
Report an issue: GitHub.