crewAIInc/crewAI · critical · RuntimeError
Failed to create or read encryption key
Error message
Failed to create or read encryption key
What it means
Raised by TokenManager._get_or_create_key after three attempts fail: reading an existing secret.key returned None or a value whose length is not 44 bytes (Fernet key length), atomically creating a new key file failed, and re-reading still failed. This means the key storage location is unwritable or unreadable — permissions, read-only filesystem, full disk, or a corrupt existing secret.key of the wrong size.
Source
Thrown at lib/crewai-core/src/crewai_core/token_manager.py:48
self.fernet = Fernet(self.key)
def _get_or_create_key(self) -> bytes:
"""Get or create the encryption key."""
key_filename: str = "secret.key"
key = self._read_secure_file(key_filename)
if key is not None and len(key) == _FERNET_KEY_LENGTH:
return key
new_key = Fernet.generate_key()
if self._atomic_create_secure_file(key_filename, new_key):
return new_key
key = self._read_secure_file(key_filename)
if key is not None and len(key) == _FERNET_KEY_LENGTH:
return key
raise RuntimeError("Failed to create or read encryption key")
def save_tokens(self, access_token: str, expires_at: int) -> None:
"""Save the access token and its expiration time.
Args:
access_token: The access token to save.
expires_at: The UNIX timestamp of the expiration time.
"""
expiration_time = datetime.fromtimestamp(expires_at)
data = {
"access_token": access_token,
"expiration": expiration_time.isoformat(),
}
encrypted_data = self.fernet.encrypt(json.dumps(data).encode())
self._atomic_write_secure_file(self.file_path, encrypted_data)
def get_token(self) -> str | None:
"""Return the access token if valid and not expired, else None."""View on GitHub (pinned to 754d7323be)
Solutions
- Check write permission on the directory where secret.key is stored and chown/chmod it for the running user.
- If secret.key exists but is corrupt, back it up and delete it so a fresh 44-byte key can be created (note: tokens encrypted with the old key become unrecoverable).
- On read-only filesystems, point the storage to a writable location or run as a user with write access.
- Free disk space if the atomic create is failing due to ENOSPC.
Example fix
# before: config dir owned by root, process runs as app user
# chown -R appuser ~/.config/crewai
# after: verify writability before constructing
from pathlib import Path
key_dir = Path.home() / ".config" / "crewai"
key_dir.mkdir(parents=True, exist_ok=True)
assert os.access(key_dir, os.W_OK), f"no write access to {key_dir}"
tm = TokenManager() Defensive patterns
Strategy: try-catch
Validate before calling
import os
from pathlib import Path
def key_store_writable() -> bool:
d = Path(".") # directory where secret.key is stored
return os.access(d, os.W_OK | os.R_OK) Try / catch
try:
tm = TokenManager()
except RuntimeError as e:
if "encryption key" in str(e):
# fix permissions on the key directory / remove corrupt secret.key, then retry once after remediation
... Prevention
- Ensure the process user owns the directory that stores secret.key (especially in Docker/CI).
- Health-check key file at startup: exists => must be exactly 44 bytes.
- Back up secret.key — deleting it makes existing tokens undecryptable.
When it happens
Trigger: Instantiating TokenManager(...) when (a) secret.key exists but is truncated/corrupt (len != 44), and (b) _atomic_create_secure_file cannot replace it because the directory is read-only, owned by another user, or the disk is full; also in sandboxes that deny writes to the key directory.
Common situations: Running the CLI in Docker/CI as a user without write access to the config dir; a partially-written key from a killed process; NFS/home-dir quota issues; running with a read-only mounted config directory.
Related errors
- Failed to update OAuth2 settings: {e!s}
- Invalid --definition path: {definition} ({exc})
- Directory {skill_dir} already exists.
- No SKILL.md found in current directory. Run this command fro
- Invalid project root for [tool.crewai] definition: {exc}
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/121f3371745a085c.
Report an issue: GitHub.