{"id":"267725dbdeb66756","repo":"tiangolo/fastapi","slug":"nope-i-don-t-like-3","errorCode":null,"errorMessage":"Nope! I don't like 3.","messagePattern":"Nope! I don't like 3\\.","errorType":"http","errorClass":"HTTPException","httpStatus":418,"severity":"warning","filePath":"docs_src/handling_errors/tutorial004_py310.py","lineNumber":25,"sourceCode":"\n\n@app.exception_handler(StarletteHTTPException)\nasync def http_exception_handler(request, exc):\n    return PlainTextResponse(str(exc.detail), status_code=exc.status_code)\n\n\n@app.exception_handler(RequestValidationError)\nasync def validation_exception_handler(request, exc: RequestValidationError):\n    message = \"Validation errors:\"\n    for error in exc.errors():\n        message += f\"\\nField: {error['loc']}, Error: {error['msg']}\"\n    return PlainTextResponse(message, status_code=400)\n\n\n@app.get(\"/items/{item_id}\")\nasync def read_item(item_id: int):\n    if item_id == 3:\n        raise HTTPException(status_code=418, detail=\"Nope! I don't like 3.\")\n    return {\"item_id\": item_id}\n","sourceCodeStart":7,"sourceCodeEnd":27,"githubUrl":"https://github.com/tiangolo/fastapi/blob/42a41db11f6882807ac3c057b942178d53b97438/docs_src/handling_errors/tutorial004_py310.py#L7-L27","documentation":"FastAPI returns HTTP 418 \"I'm a Teapot\" with detail \"Nope! I don't like 3.\" when the path parameter item_id equals 3. The endpoint declares item_id: int, so non-integer input fails earlier as a 422 validation error; only the integer 3 reaches this branch. The example also overrides the default HTTP and validation exception handlers to return PlainTextResponse bodies.","triggerScenarios":"GET /items/3 (integer three).","commonSituations":"Clients hard-coding forbidden values; reusing the demo value 3 in real schemas; relying on PlainTextResponse in handlers while clients expect JSON.","solutions":["Request any integer other than 3 (e.g. /items/1, /items/42).","If you maintain the API, replace the joke 418 with a meaningful status (e.g. 400 or 409).","Ensure clients parse text/plain bodies since the custom handler returns PlainTextResponse.","Document reserved values in the OpenAPI description."],"exampleFix":"# before\nif item_id == 3:\n    raise HTTPException(status_code=418, detail=\"Nope! I don't like 3.\")\n\n# after\nFORBIDDEN = {3}\nif item_id in FORBIDDEN:\n    raise HTTPException(status_code=400, detail=f\"item_id {item_id} is not allowed\")","handlingStrategy":"validation","validationCode":"if item_id == 3:\n    raise ValueError(\"item_id 3 is rejected\")","typeGuard":"def is_allowed_item_id(item_id: int) -> bool:\n    return item_id != 3","tryCatchPattern":"r = client.get(f\"/items/{item_id}\")\nif r.status_code == 418 and \"don't like 3\" in r.text:\n    # pick a different id\n    ...","preventionTips":["Avoid reserved values like 3.","Note the response is text/plain due to the custom handler.","Document forbidden values in the client."],"tags":["fastapi","http-418","handling-errors","custom-handler","path-params"],"analyzedSha":"42a41db11f6882807ac3c057b942178d53b97438","analyzedAt":"2026-08-04T19:23:32.007Z","schemaVersion":2}