BerriAI/litellm · critical · FileNotFoundError
Private key file not found: {file_path}
Error message
Private key file not found: {file_path} What it means
load_private_key_from_file re-raises FileNotFoundError with a clearer message when the path given via oci_key_file / OCI_KEY_FILE does not exist. It is a configuration error: the signing path resolved a key path, but the filesystem has no file there.
Source
Thrown at litellm/llms/oci/common_utils.py:133
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)
# ---------------------------------------------------------------------------
# Env-var credential resolution
# ---------------------------------------------------------------------------
_OCI_REGION_ENV: Final = "OCI_REGION"
_OCI_USER_ENV: Final = "OCI_USER"
_OCI_FINGERPRINT_ENV: Final = "OCI_FINGERPRINT"
_OCI_TENANCY_ENV: Final = "OCI_TENANCY"
_OCI_KEY_FILE_ENV: Final = "OCI_KEY_FILE"View on GitHub (pinned to 6c2dcb801b)
Solutions
- Check the exact path: use an absolute path for oci_key_file / OCI_KEY_FILE.
- In containers, confirm the secret/volume is mounted at that path (kubectl exec ls).
- Expand user paths programmatically: os.path.expanduser() before passing.
- Alternatively embed the PEM content directly via oci_key to remove the filesystem dependency.
Example fix
# before
os.environ["OCI_KEY_FILE"] = "~/.oci/oci_api_key.pem" # literal ~ not expanded
# after
import os
os.environ["OCI_KEY_FILE"] = os.path.expanduser("~/.oci/oci_api_key.pem")
assert os.path.exists(os.environ["OCI_KEY_FILE"]) Defensive patterns
Strategy: validation
Validate before calling
import os
key_path = os.path.expanduser(os.environ.get("OCI_KEY_FILE", ""))
assert key_path and os.path.isfile(key_path), f"OCI key file missing: {key_path!r}" Try / catch
try:
litellm.completion(model="oci/...", messages=m)
except FileNotFoundError as e:
if "Private key file" in str(e):
raise ConfigError(f"mount/copy the key to {path_from_error}") from e
raise Prevention
- Always use absolute, expanduser'd paths for OCI_KEY_FILE.
- Assert file existence at startup in every environment.
- Prefer inline OCI_KEY from a secret manager to avoid filesystem coupling.
When it happens
Trigger: OCI_KEY_FILE set to a relative path that resolves differently in the deployed cwd; Docker container missing the mounted key volume; typo in the path; key file present locally but absent in CI/prod; '~' not expanded.
Common situations: Works-on-my-machine path bugs: '~/.oci/oci_api_key.pem' left unexpanded by a non-shell process, paths from an .env file not mounted into the container, volume mount path mismatch in Kubernetes secrets, or a typo'd filename.
Related errors
- Private key file is empty: {file_path}
- Missing required OCI credentials: oci_user, oci_fingerprint,
- Error: {response.status_code} - {response.text}
- Missing Authorization header
- Invalid bearer token
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/2117ffe27e57fd35.
Report an issue: GitHub.