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
- Validate the body with a local YAML parser (e.g. `yaml.safe_load`) before sending.
- Ensure Content-Type is application/x-yaml and the body uses spaces, not tabs.
- Differentiate this 422 from the Pydantic-validation 422 in client error handling by inspecting detail text.
- 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
- Lint YAML locally before sending.
- Use spaces, never tabs, in indentation.
- Set Content-Type to application/x-yaml explicitly.
- Differentiate parse-422 from schema-422 in client error handling.
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
- e.errors(include_url=False)
- {"errors": exc.errors(), "body": body.decode()}
- {"errors": exc.errors(), "body": body.decode()}
- Invalid ID format, it must start with "isbn-" or "imdb-"
- Expected UploadFile, received: {type(__input_value)}
AI-assisted analysis of tiangolo/fastapi@42a41db11f (2026-08-04).
Data as JSON: /data/errors/94b1e6047b5c8990.json.
Report an issue: GitHub.