trailofbits/algo · error · OSError
Failed to read private key file: {e}
Error message
Failed to read private key file: {e} What it means
The module could not read the file given as private_key_path: the OS raised OSError (file not found, permission denied, or an I/O error) during open()/read(). The exception text is embedded in the message.
Source
Thrown at library/x25519_pubkey.py:77
data = f.read()
try:
# First attempt: assume file contains base64 text data
# Strip whitespace from edges for text files (safe for base64 strings)
stripped_data = data.strip()
base64.b64decode(stripped_data, validate=True)
priv_b64 = stripped_data.decode()
except (base64.binascii.Error, ValueError):
# Second attempt: assume file contains raw binary data
# CRITICAL: Do NOT strip raw binary data - X25519 keys can contain
# whitespace-like bytes (0x09, 0x0A, etc.) that must be preserved
# Stripping would corrupt the key and cause "got 31 bytes" errors
if len(data) != 32:
module.fail_json(
msg=f"Private key file must be either base64 or exactly 32 raw bytes, got {len(data)} bytes"
)
priv_b64 = base64.b64encode(data).decode()
except OSError as e:
module.fail_json(msg=f"Failed to read private key file: {e}")
else:
priv_b64 = module.params["private_key_b64"]
# Validate input parameters
if not priv_b64:
module.fail_json(msg="No private key provided")
try:
priv_raw = base64.b64decode(priv_b64, validate=True)
except Exception as e:
module.fail_json(msg=f"Invalid base64 private key format: {e}")
if len(priv_raw) != 32:
module.fail_json(msg=f"Private key must decode to exactly 32 bytes, got {len(priv_raw)}")
try:
priv_key = x25519.X25519PrivateKey.from_private_bytes(priv_raw)
pub_key = priv_key.public_key()View on GitHub (pinned to 20e22a8715)
Solutions
- Check the path exists: ls -l <private_key_path>
- Fix ownership/permissions: sudo chown -R $USER configs/ && chmod 600 <keyfile>
- Use an absolute path in the task
- If generated in a previous task, verify the key-generation task actually ran and produced the file
Defensive patterns
Strategy: validation
Validate before calling
import os
p = '/path/to/priv.key'
assert os.path.isfile(p) and os.access(p, os.R_OK), f'cannot read {p}' Type guard
def readable_file(p: str) -> bool:
import os
return bool(p) and os.path.isfile(p) and os.access(p, os.R_OK) Prevention
- Use absolute paths in playbooks
- Keep configs/ owned by the ansible user
- Create key files with mode '0600'
When it happens
Trigger: private_key_path points to a nonexistent path, a file the Ansible user cannot read (bad ownership/mode on configs/), or a directory/IS-A-FILE error.
Common situations: Running ansible as a different user than the one that generated keys, wrong relative path (resolved relative to the play, not the roles dir), or configs/ owned by root.
Related errors
- Failed to write public key file: {e}
- Private key file must be either base64 or exactly 32 raw byt
- No private key provided
- Invalid base64 private key format: {e}
- Private key must decode to exactly 32 bytes, got {len(priv_r
AI-assisted analysis of trailofbits/algo@20e22a8715 (2026-08-28).
Data as JSON: /api/errors/561f13da759f8606.
Report an issue: GitHub.