trailofbits/algo · error
No private key provided
Error message
No private key provided
What it means
Neither private_key_path nor private_key_b64 yielded a key: the file branch was not taken (path not provided) and private_key_b64 is empty/None/falsy, so the module aborts before any cryptography work.
Source
Thrown at library/x25519_pubkey.py:83
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()
pub_raw = pub_key.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw)
pub_b64 = base64.b64encode(pub_raw).decode()
result["public_key"] = pub_b64
if module.params["public_key_path"]:
pub_path = module.params["public_key_path"]View on GitHub (pinned to 20e22a8715)
Solutions
- Pass exactly one of private_key_path or private_key_b64
- Debug the variable feeding private_key_b64: add - debug: var=... to confirm it is non-empty
- Use | default(..., true) if the source variable may be an empty string
- Check the parameter spelling against the module's argument_spec
Example fix
# before
private_key_b64: "{{ user_key }}"
# after
private_key_b64: "{{ user_key | default('', true) }}{{ '' if not user_key else user_key }}" # or ensure user_key is set
# better: assert the var first
- assert:
that: user_key | default('', true) | length > 0 Defensive patterns
Strategy: validation
Validate before calling
- assert:
that:
- (private_key_b64 | default('', true) | length) > 0 or (private_key_path | default('', true) | length) > 0 Prevention
- Always assert required key variables before the module task
- Use default(..., true) so empty strings are treated as missing
When it happens
Trigger: Calling the module with neither argument, with private_key_b64: "" or a Jinja variable that rendered empty (undefined var defaulting to empty string).
Common situations: Jinja2 native mode returning empty strings for undefined variables, typo in the parameter name, or a preceding key-generation task skipped by a when condition.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- Private key file must be either base64 or exactly 32 raw byt
- Failed to read private key file: {e}
- Invalid base64 private key format: {e}
- Private key must decode to exactly 32 bytes, got {len(priv_r
- Failed to write public key file: {e}
AI-assisted analysis of trailofbits/algo@20e22a8715 (2026-08-28).
Data as JSON: /api/errors/3bc5bfb0a8577d60.
Report an issue: GitHub.