BerriAI/litellm · critical · OSError
Failed to read private key file '{file_path}': {e}
Error message
Failed to read private key file '{file_path}': {e} What it means
load_private_key_from_file catches OSError (permission denied, directory-level I/O errors, SELinux denials) while opening the key file and re-raises it with context about which file failed. It signals the file exists but the process cannot read it.
Source
Thrown at litellm/llms/oci/common_utils.py:135
_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"
_OCI_KEY_ENV: Final = "OCI_KEY"
_OCI_COMPARTMENT_ID_ENV: Final = "OCI_COMPARTMENT_ID"View on GitHub (pinned to 6c2dcb801b)
Solutions
- Fix ownership/permissions: chown <appuser> key.pem; chmod 400 key.pem.
- In Kubernetes, set securityContext.fsGroup to the group that owns the mounted secret.
- For SELinux hosts, label the volume correctly (z/Z mount option in Docker: -v ...:/secrets:ro,z).
- Verify as the app user: sudo -u appuser cat <keyfile>.
Example fix
# before — root-owned key, app cannot read # docker: COPY --chown=root oci_key.pem /secrets/ → OSError # after # Dockerfile: COPY --chown=1000:1000 oci_key.pem /secrets/ # or run: chmod 400 + chown appuser
Defensive patterns
Strategy: validation
Validate before calling
import os
p = os.path.expanduser(os.environ["OCI_KEY_FILE"])
assert os.path.isfile(p) and os.access(p, os.R_OK), f"cannot read key file: {p} (perms/owner?)" Try / catch
try:
litellm.completion(model="oci/...", messages=m)
except OSError as e:
if "Failed to read private key file" in str(e):
fix_ownership_or_die() # chown/chmod, fsGroup, SELinux label
raise Prevention
- Set fsGroup in Kubernetes securityContext for secret mounts.
- chmod 400 and chown to the runtime user in Docker images.
- Use the -v :ro,z mount option on SELinux hosts.
When it happens
Trigger: Key file owned by root while the app runs as a non-root user (mode 600, uid mismatch); read-only or corrupted mount; path points at a directory component with no execute permission; SELinux/AppArmor blocking reads on the secret mount.
Common situations: Docker containers running as app user with a secret mounted as root-owned; Kubernetes secret mounted read-only with restrictive fsGroup settings; files copied with sudo leaving 600 root:root; SELinux-enabled hosts (RHEL/CoreOS) denying container access.
Related errors
- Access denied to file '{file_path}'. Check your BitBucket pe
- Access denied to directory '{directory_path}'. Check your Bi
- {e.response.text}
- The provided private key is not an RSA key, which is require
- Private key file not found: {file_path}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/16cf43eec1b87301.
Report an issue: GitHub.