BerriAI/litellm · error · BadRequestError

invalid_encrypted_content

invalid_encrypted_content

Error message

AzureException - {message}

This error occurs when load balancing Responses API across deployments with different API keys.
   Encrypted content is tied to the organization that created it and cannot be decrypted by other organizations.

   Solution: Enable 'encrypted_content_affinity' to route follow-up requests to the correct deployment:

   router_settings:
     enable_pre_call_checks: true
     optional_pre_call_checks:
       - encrypted_content_affinity

   Learn more: https://docs.litellm.ai/docs/response_api#encrypted-content-affinity-multi-region-load-balancing

What it means

litellm maps Azure 'invalid_encrypted_content' (or 'could not be verified' in the error) to litellm.BadRequestError, appending a detailed hint. Azure Responses API returns encrypted reasoning items; encrypted content is bound to the creating organization, so follow-up requests routed to a deployment with different keys cannot decrypt it.

Source

Thrown at litellm/litellm_core_utils/exception_mapping_utils.py:1945

        raise AzureOpenAIExceptionMapping.create_content_policy_violation_error(
            message=message,
            model=model,
            extra_information=extra_information,
            original_exception=original_exception,
        )
    elif azure_error_code == "invalid_encrypted_content" or "could not be verified" in error_str:
        helpful_message: Final = (
            f"AzureException - {message}\n\n"
            "This error occurs when load balancing Responses API across deployments with different API keys.\n"
            "   Encrypted content is tied to the organization that created it and cannot be decrypted by other organizations.\n\n"
            "   Solution: Enable 'encrypted_content_affinity' to route follow-up requests to the correct deployment:\n\n"
            "   router_settings:\n"
            "     enable_pre_call_checks: true\n"
            "     optional_pre_call_checks:\n"
            "       - encrypted_content_affinity\n\n"
            "   Learn more: https://docs.litellm.ai/docs/response_api#encrypted-content-affinity-multi-region-load-balancing"
        )
        raise BadRequestError(
            message=helpful_message,
            llm_provider="azure",
            model=model,
            litellm_debug_info=extra_information,
            response=getattr(original_exception, "response", None),
            body=getattr(original_exception, "body", None),
        )
    elif "invalid_request_error" in error_str and getattr(original_exception, "status_code", None) in (None, 400):
        raise BadRequestError(
            message=f"AzureException BadRequestError - {message}",
            llm_provider="azure",
            model=model,
            litellm_debug_info=extra_information,
            response=getattr(original_exception, "response", None),
            body=getattr(original_exception, "body", None),
        )
    elif "The api_key client option must be set either by passing api_key to the client or by setting" in error_str:
        raise AuthenticationError(

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Enable the built-in pre-call check exactly as the error says: router_settings: enable_pre_call_checks: true with optional_pre_call_checks: [encrypted_content_affinity]
  2. Alternatively pin each conversation to one deployment (sticky sessions by session_id)
  3. Or use only deployments sharing the same Azure organization/key for Responses API traffic
  4. As a last resort disable returning encrypted content (azure reasoning options) so no encrypted items circulate
  5. See https://docs.litellm.ai/docs/response_api#encrypted-content-affinity-multi-region-load-balancing

Example fix

# before
router_settings:
  num_deployments: 3  # azure responses deployments, different keys -> 400 on follow-ups
# after (proxy config.yaml)
router_settings:
  enable_pre_call_checks: true
  optional_pre_call_checks:
    - encrypted_content_affinity
Defensive patterns

Strategy: validation

Validate before calling

# proxy config.yaml - gate before any Responses API traffic
router_settings:
  enable_pre_call_checks: true
  optional_pre_call_checks:
    - encrypted_content_affinity

Type guard

import litellm

def is_encrypted_content_affinity_error(e: Exception) -> bool:
    return isinstance(e, litellm.BadRequestError) and ('could not be verified' in str(e) or 'encrypted_content' in str(e))

Try / catch

try:
    resp = litellm.responses(model='azure/gpt-4o', input=items)
except litellm.BadRequestError as e:
    if 'could not be verified' in str(e):
        pin_session_to_single_deployment(session_id)  # then replay once
    raise

Prevention

When it happens

Trigger: Load-balancing the Azure Responses API (responses(), previous_response_id or encrypted reasoning items in input) across deployments with different API keys/organizations: the first call creates encrypted content under org A, the retry/follow-up hits org B's deployment, Azure returns invalid_encrypted_content, and litellm raises BadRequestError with the affinity guidance.

Common situations: litellm Router/proxy setups with multiple Azure Responses API deployments on separate keys; failover mid-conversation; multi-region load balancing without sticky routing.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/7688f95ce369a875. Report an issue: GitHub.