tiangolo/fastapi · error · HTTPException

Invalid YAML

Error message

Invalid YAML

What it means

FastAPI returns HTTP 422 "Invalid YAML" when `yaml.safe_load(raw_body)` raises a `yaml.YAMLError` while parsing the request body declared (via openapi_extra) as application/x-yaml. The endpoint reads the raw body manually because FastAPI does not natively bind YAML bodies, then validates the parsed dict against the Item Pydantic model. This 422 specifically denotes a YAML syntax failure distinct from the subsequent Pydantic validation 422.

Source

Thrown at docs_src/path_operation_advanced_configuration/tutorial007_py310.py:27

    name: str
    tags: list[str]


@app.post(
    "/items/",
    openapi_extra={
        "requestBody": {
            "content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
            "required": True,
        },
    },
)
async def create_item(request: Request):
    raw_body = await request.body()
    try:
        data = yaml.safe_load(raw_body)
    except yaml.YAMLError:
        raise HTTPException(status_code=422, detail="Invalid YAML")
    try:
        item = Item.model_validate(data)
    except ValidationError as e:
        raise HTTPException(status_code=422, detail=e.errors(include_url=False))
    return item

View on GitHub (pinned to 42a41db11f)

Solutions

  1. Validate the body with a local YAML parser (e.g. `yaml.safe_load`) before sending.
  2. Ensure Content-Type is application/x-yaml and the body uses spaces, not tabs.
  3. Differentiate this 422 from the Pydantic-validation 422 in client error handling by inspecting detail text.
  4. Return a more descriptive detail (e.g. include the parser's line number) to aid debugging.

Example fix

# before
try:
    data = yaml.safe_load(raw_body)
except yaml.YAMLError:
    raise HTTPException(status_code=422, detail="Invalid YAML")

# after
try:
    data = yaml.safe_load(raw_body)
except yaml.YAMLError as e:
    raise HTTPException(status_code=422, detail=f"Invalid YAML: {e}")
Defensive patterns

Strategy: validation

Validate before calling

import yaml
body_text = open("payload.yaml").read()
try:
    yaml.safe_load(body_text)
except yaml.YAMLError as e:
    raise ValueError(f"body is not valid YAML: {e}")
client.post("/items/", content=body_text, headers={"Content-Type": "application/x-yaml"})

Type guard

def is_valid_yaml(text: str) -> bool:
    try:
        yaml.safe_load(text)
        return True
    except yaml.YAMLError:
        return False

Try / catch

r = client.post("/items/", content=body, headers={"Content-Type": "application/x-yaml"})
if r.status_code == 422 and "Invalid YAML" in r.text:
    # distinguish YAML-parse 422 from Pydantic-validation 422
    ...

Prevention

When it happens

Trigger: POST /items/ with Content-Type: application/x-yaml and a body that is not well-formed YAML (e.g. unbalanced indentation, bad mapping syntax, tabs where spaces are required).

Common situations: Clients sending JSON to a YAML-only endpoint; copy/paste introducing tabs; encodings/BOM; CI generating YAML with a faulty template; version drift in the YAML library producing stricter parsing.

Related errors


AI-assisted analysis of tiangolo/fastapi@42a41db11f (2026-08-04). Data as JSON: /data/errors/94b1e6047b5c8990.json. Report an issue: GitHub.