BerriAI/litellm · error · RuntimeError
Encryption migration requires general_settings.encryption_al
Error message
Encryption migration requires general_settings.encryption_algorithm: 'aes-256-gcm'. Current value: {algo!r}. Set it before migrating so re-encrypted values are written in the AES-256-GCM format. What it means
RuntimeError raised by _assert_aes_gate_enabled() before the credential re-encryption migration runs: it reads general_settings.encryption_algorithm from the running proxy config and requires the exact value 'aes-256-gcm' (case-insensitive). The guard exists because running the migration with the AES gate off would decrypt legacy nacl ciphertext and immediately re-encrypt it back into the legacy format — a silent no-op migration — so it fails fast instead.
Source
Thrown at litellm/proxy/management_endpoints/credential_migration.py:185
for k in sensitive_keys:
v = out.get(k)
if v is None:
continue
out[k] = reencrypt_value(v, key=k)
return out
def _assert_aes_gate_enabled() -> None:
"""Fail fast if the AES algorithm gate is not enabled.
Running the migration with the gate off would decrypt then re-encrypt right
back into the legacy format — a no-op that silently fails the migration.
"""
from litellm.proxy.proxy_server import general_settings
algo: Final = general_settings.get(_ENCRYPTION_ALGORITHM_SETTING)
if not (isinstance(algo, str) and algo.lower() == _ALGO_AES_GCM):
raise RuntimeError(
"Encryption migration requires general_settings.encryption_algorithm: "
f"'{_ALGO_AES_GCM}'. Current value: {algo!r}. Set it before migrating "
"so re-encrypted values are written in the AES-256-GCM format."
)
# ---------------------------------------------------------------------------
# Walkers for the locations with no pre-existing rotation path.
# Each walker delegates the structural transform to the existing, tested helper
# for that table and only adds the per-row re-encrypt + commit + counters.
# ---------------------------------------------------------------------------
async def _migrate_config_settings_row(
prisma_client: object,
param_name: str,
sensitive_fields: list[str],
dry_run: bool,View on GitHub (pinned to 77b7c6c40c)
Solutions
- In the proxy config, set general_settings.encryption_algorithm: aes-256-gcm and restart/reload so general_settings in the running server carries it.
- Re-run the migration; the guard is a pure precondition — no state was touched when it raised.
- Keep the same master key: the migration re-encrypts under the same derived key, so do not rotate the key at the same time.
- After migration, verify with the read-only check_encryption scan that residual legacy == 0.
Example fix
# before (config.yaml) litellm_settings: encryption_algorithm: aes-256-gcm # wrong section -> RuntimeError(None) # after general_settings: encryption_algorithm: aes-256-gcm
Defensive patterns
Strategy: validation
Validate before calling
import yaml, requests
cfg = yaml.safe_load(open("config.yaml"))
algo = cfg.get("general_settings", {}).get("encryption_algorithm", "")
if str(algo).lower() != "aes-256-gcm":
raise SystemExit(
"Set general_settings.encryption_algorithm: aes-256-gcm and restart the proxy "
"before running the encryption migration."
) Try / catch
try:
run_encryption_migration(prisma_client)
except RuntimeError as e:
if "encryption_algorithm" in str(e):
# precondition failure: nothing was migrated; fix config and restart proxy, then re-run
set_general_setting("encryption_algorithm", "aes-256-gcm")
restart_proxy()
run_encryption_migration(prisma_client) # idempotent, safe to re-run
else:
raise Prevention
- Treat general_settings.encryption_algorithm: aes-256-gcm as a checklist precondition of the migration runbook.
- Restart (or hot-reload) the proxy after changing the setting so its in-memory general_settings is updated.
- Run the read-only check_encryption scan before and after; residual legacy == 0 is your attestation.
- Never rotate the master key and the algorithm in the same operation.
When it happens
Trigger: Invoking the encryption migration (the credential_migration module's migrate/check flows) while general_settings.encryption_algorithm is unset (None), set to the legacy default, or misspelled; setting the key somewhere the running proxy doesn't read (wrong config file, env not loaded).
Common situations: Compliance-driven migrations from XSalsa20-Poly1305 to AES-256-GCM where the operator forgot the prerequisite config step; setting encryption_algorithm after the proxy started without restarting; YAML indentation putting the key outside general_settings.
Related errors
- mcp_tools_config is required, please set `mcp_tools` in your
- mcp_tools_config must be a list of dictionaries
- git-subdir 'path' must be a relative path of the form 'segme
- No db connected
- No DB Connected. See - https://docs.litellm.ai/docs/proxy/vi
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/70f94a58df9289a6.
Report an issue: GitHub.