BerriAI/litellm · error · BedrockError

guardrailConfig={raw_guardrail_config} is missing 'guardrail

Error message

guardrailConfig={raw_guardrail_config} is missing 'guardrailIdentifier'. Expected format: {_GUARDRAIL_CONFIG_EXPECTED_FORMAT}

What it means

Raised by _bedrock_invoke_guardrail_headers when the validated guardrailConfig dict is missing the required 'guardrailIdentifier' key. This is a separate check after pydantic validation (which permits the key to be absent), producing a BedrockError 400 that echoes the raw config and the expected format string.

Source

Thrown at litellm/llms/bedrock/chat/invoke_transformations/base_invoke_transformation.py:58

from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM

_GUARDRAIL_CONFIG_VALIDATOR: Final["TypeAdapter[GuardrailConfigBlock]"] = TypeAdapter(GuardrailConfigBlock)

_GUARDRAIL_CONFIG_EXPECTED_FORMAT: Final = (
    "{'guardrailIdentifier': str, 'guardrailVersion': str, 'trace': 'enabled'|'disabled'|'enabled_full'}"
)


def _bedrock_invoke_guardrail_headers(raw_guardrail_config: object) -> "dict[str, str]":
    try:
        guardrail_config: Final = _GUARDRAIL_CONFIG_VALIDATOR.validate_python(raw_guardrail_config)
    except ValidationError as e:
        raise BedrockError(
            status_code=400,
            message=f"Invalid guardrailConfig={raw_guardrail_config}. Expected format: {_GUARDRAIL_CONFIG_EXPECTED_FORMAT}. Error: {e}",
        )
    if "guardrailIdentifier" not in guardrail_config:
        raise BedrockError(
            status_code=400,
            message=f"guardrailConfig={raw_guardrail_config} is missing 'guardrailIdentifier'. Expected format: {_GUARDRAIL_CONFIG_EXPECTED_FORMAT}",
        )
    trace: Final = guardrail_config.get("trace")
    candidate_headers: Final = {
        "X-Amzn-Bedrock-GuardrailIdentifier": guardrail_config.get("guardrailIdentifier"),
        "X-Amzn-Bedrock-GuardrailVersion": guardrail_config.get("guardrailVersion"),
        "X-Amzn-Bedrock-Trace": trace.upper() if trace is not None else None,
    }
    return {name: value for name, value in candidate_headers.items() if value is not None}


class AmazonInvokeConfig(BaseConfig, BaseAWSLLM):
    def __init__(self, **kwargs):
        BaseConfig.__init__(self, **kwargs)
        BaseAWSLLM.__init__(self, **kwargs)

    def get_supported_openai_params(self, model: str) -> list[str]:

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Add 'guardrailIdentifier' with your guardrail ID or full ARN (e.g. 'gr-abcdef123' or 'arn:aws:bedrock:us-east-1:...:guardrail/gr-...').
  2. If building config dynamically, skip guardrailConfig entirely when no identifier is configured instead of sending a partial dict.
  3. Do not send guardrail headers at all if you do not want guardrails applied.

Example fix

# before
extra_body={"guardrailConfig": {"guardrailVersion": "1", "trace": "enabled"}}

# after
extra_body={"guardrailConfig": {
    "guardrailIdentifier": "gr-abcdef123",
    "guardrailVersion": "1",
    "trace": "enabled",
}}
Defensive patterns

Strategy: validation

Validate before calling

if use_guardrails:
    if not guardrail_identifier:
        raise ValueError("guardrailIdentifier is required when guardrails are enabled")
    extra_body = {"guardrailConfig": {
        "guardrailIdentifier": guardrail_identifier,
        "guardrailVersion": guardrail_version or "1",
        "trace": trace or "enabled",
    }}
else:
    extra_body = {}  # send nothing rather than a partial config

Type guard

def has_guardrail_identifier(cfg: object) -> bool:
    return isinstance(cfg, dict) and isinstance(cfg.get("guardrailIdentifier"), str) and len(cfg["guardrailIdentifier"]) > 0

Try / catch

from litellm.exceptions import BedrockError
try:
    litellm.completion(model="bedrock/<model>", messages=msgs, extra_body={"guardrailConfig": cfg})
except BedrockError as e:
    if e.status_code == 400 and "missing 'guardrailIdentifier'" in str(e):
        cfg.setdefault("guardrailIdentifier", DEFAULT_GUARDRAIL_ID)
        retry()
    raise

Prevention

When it happens

Trigger: Passing a guardrailConfig like {'guardrailVersion': '1'} or {'trace': 'enabled'} without a guardrailIdentifier to a bedrock/ invoke call that activates guardrail header generation.

Common situations: Developers enabling trace-only usage and assuming the identifier is optional, config built dynamically where the identifier key is dropped when its value is None, or copy-paste from partial examples.

Related errors


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