BerriAI/litellm · error · HTTPException

Guardrail configuration error: {init_error}

Error message

Guardrail configuration error: {init_error}

What it means

POST /guardrails returns HTTP 400 'Guardrail configuration error: ...' when the guardrail row was written to the DB but IN_MEMORY_GUARDRAIL_HANDLER.initialize_guardrail() raised ValueError or TypeError — meaning the saved litellm_params are structurally invalid for instantiating the guardrail (unknown guardrail type, missing mode, bad field types). The handler rolls back the just-inserted row so no orphaned guardrail remains, then surfaces the underlying message.

Source

Thrown at litellm/proxy/guardrails/guardrail_endpoints.py:423

    try:
        result = await GUARDRAIL_REGISTRY.add_guardrail_to_db(guardrail=request.guardrail, prisma_client=prisma_client)

        guardrail_name: Final = result.get("guardrail_name", "Unknown")
        guardrail_id: Final = result.get("guardrail_id", "Unknown")

        try:
            IN_MEMORY_GUARDRAIL_HANDLER.initialize_guardrail(guardrail=cast(Guardrail, result), source="db")
            verbose_proxy_logger.info(
                "Immediate sync: Successfully initialized guardrail '%s' (ID: %s)", guardrail_name, guardrail_id
            )
        except (ValueError, TypeError) as init_error:
            # Configuration error — roll back the DB write so the guardrail isn't orphaned
            if prisma_client is not None:
                try:
                    await _delete_guardrail_row(prisma_client, where={"guardrail_id": guardrail_id})
                except Exception as rollback_err:
                    verbose_proxy_logger.warning("Rollback failed for guardrail '%s': %s", guardrail_id, rollback_err)
            raise HTTPException(
                status_code=400,
                detail=f"Guardrail configuration error: {init_error}",
            )
        except Exception as init_error:
            verbose_proxy_logger.warning(
                "Immediate sync: Failed to initialize guardrail '%s' (ID: %s) in memory: %s",
                guardrail_name,
                guardrail_id,
                init_error,
            )

        return result
    except Exception as e:
        verbose_proxy_logger.exception("Error adding guardrail to db: %s", e)
        raise HTTPException(status_code=500, detail=str(e))


class UpdateGuardrailRequest(BaseModel):

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Read the {init_error} suffix — it names the exact missing/invalid field; fix the litellm_params in the request body accordingly
  2. Validate against the Guardrail pydantic schema and the target guardrail integration's required params (e.g. mode: pre_call, guardrailIdentifier, guardrailVersion for bedrock) before resubmitting
  3. Check that litellm_params.guardrail matches a registered guardrail handler name in your LiteLLM version
  4. The DB row was auto-rolled-back, so simply correct and re-POST — no manual cleanup needed unless rollback itself logged a warning

Example fix

# before
{"guardrail_name": "my-guard", "litellm_params": {"guardrail": "bedrok", "mode": "pre_call"}}

# after
{"guardrail_name": "my-guard", "litellm_params": {"guardrail": "bedrock", "mode": "pre_call", "guardrailIdentifier": "ff6ujrregl1q", "guardrailVersion": "DRAFT"}}
Defensive patterns

Strategy: validation

Validate before calling

REQUIRED_LITELLM_PARAMS = {"guardrail", "mode"}

def guardrail_params_look_valid(lp: dict) -> list[str]:
    missing = [k for k in REQUIRED_LITELLM_PARAMS if not lp.get(k)]
    if lp.get("guardrail") == "bedrock":
        missing += [k for k in ("guardrailIdentifier", "guardrailVersion") if not lp.get(k)]
    return missing

problems = guardrail_params_look_valid(request_body["litellm_params"])
if problems:
    raise ValueError(f"Guardrail config missing: {problems}")

Type guard

def is_known_guardrail_type(name: str) -> bool:
    known = {"bedrock", "aim", "presidio", "lakera", "aporia", "generic_guardrail_api"}
    return name in known

Try / catch

try:
    r = requests.post(f"{proxy}/guardrails", json=guardrail, headers=h, timeout=30)
    r.raise_for_status()
except requests.HTTPError as e:
    if e.response is not None and e.response.status_code == 400 and "configuration error" in e.response.text.lower():
        # server rolled back the row; fix litellm_params from detail and re-submit
        log.warning("Guardrail rejected: %s", e.response.text)
        raise ValueError(e.response.text) from e
    raise

Prevention

When it happens

Trigger: Creating a guardrail whose litellm_params.guardrail is an unsupported type name, omitting required params like mode or guardrailIdentifier/guardrailVersion for bedrock, or providing values with wrong types (e.g. default_on as string) so the runtime guardrail constructor throws ValueError/TypeError.

Common situations: Typos in the guardrail provider key ('bedrock' vs 'bedrock_guard'), configs copied from an older LiteLLM version whose param names changed, or a new custom guardrail class whose expected kwargs drifted from the API payload.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


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