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

  1. In the proxy config, set general_settings.encryption_algorithm: aes-256-gcm and restart/reload so general_settings in the running server carries it.
  2. Re-run the migration; the guard is a pure precondition — no state was touched when it raised.
  3. Keep the same master key: the migration re-encrypts under the same derived key, so do not rotate the key at the same time.
  4. 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

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


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/70f94a58df9289a6. Report an issue: GitHub.