{"id":"23ef81dae03fef0d","repo":"tiangolo/fastapi","slug":"invalid-x-token-header","errorCode":null,"errorMessage":"Invalid X-Token header","messagePattern":"Invalid X-Token header","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"docs_src/app_testing/app_b_an_py310/main.py","lineNumber":25,"sourceCode":"\nfake_db = {\n    \"foo\": {\"id\": \"foo\", \"title\": \"Foo\", \"description\": \"There goes my hero\"},\n    \"bar\": {\"id\": \"bar\", \"title\": \"Bar\", \"description\": \"The bartenders\"},\n}\n\napp = FastAPI()\n\n\nclass Item(BaseModel):\n    id: str\n    title: str\n    description: str | None = None\n\n\n@app.get(\"/items/{item_id}\", response_model=Item)\nasync def read_main(item_id: str, x_token: Annotated[str, Header()]):\n    if x_token != fake_secret_token:\n        raise HTTPException(status_code=400, detail=\"Invalid X-Token header\")\n    if item_id not in fake_db:\n        raise HTTPException(status_code=404, detail=\"Item not found\")\n    return fake_db[item_id]\n\n\n@app.post(\"/items/\")\nasync def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item:\n    if x_token != fake_secret_token:\n        raise HTTPException(status_code=400, detail=\"Invalid X-Token header\")\n    if item.id in fake_db:\n        raise HTTPException(status_code=409, detail=\"Item already exists\")\n    fake_db[item.id] = item.model_dump()\n    return item\n","sourceCodeStart":7,"sourceCodeEnd":39,"githubUrl":"https://github.com/tiangolo/fastapi/blob/42a41db11f6882807ac3c057b942178d53b97438/docs_src/app_testing/app_b_an_py310/main.py#L7-L39","documentation":"This HTTPException is raised by the GET /items/{item_id} handler in the app-testing example when the incoming X-Token request header does not equal the hardcoded secret token (\"coneofsilence\"). FastAPI uses HTTPException to short-circuit the request and return a structured JSON error response with HTTP status 400 instead of running the rest of the handler. It is a simple bearer-style guard meant to demonstrate authentication on a protected read endpoint.","triggerScenarios":"A GET /items/{item_id} request where the X-Token header is absent, empty, or any value other than \"coneofsilence\" (e.g. curl http://host/items/foo without -H \"X-Token: coneofsilence\").","commonSituations":"Test clients (httpx/TestClient) that forget to attach the header; frontend code that drops headers on a refresh; copying an example with a placeholder token; deploying with a token that differs from the client's configured value.","solutions":["Send the header X-Token: coneofsilence on every GET /items/{item_id} request.","If using TestClient, pass headers={\"X-Token\": \"coneofsilence\"} in the call.","Replace the hardcoded token with a value loaded from settings/env so client and server agree.","Confirm the header name casing/underscore: FastAPI maps x_token to the X-Token header."],"exampleFix":"# before\nclient.get(\"/items/foo\")\n# after\nclient.get(\"/items/foo\", headers={\"X-Token\": \"coneofsilence\"})","handlingStrategy":"validation","validationCode":"# Validate the token is present and correct before sending\nEXPECTED_TOKEN = \"coneofsilence\"\nassert EXPECTED_TOKEN, \"X-Token not configured\"\nheaders = {\"X-Token\": EXPECTED_TOKEN} if EXPECTED_TOKEN else {}","typeGuard":"def has_valid_token(token: str | None) -> bool:\n    return token is not None and token == \"coneofsilence\"","tryCatchPattern":null,"preventionTips":["Store the token in an env var and load it once at startup.","Wrap all requests in a helper that injects the X-Token header.","In tests, assert the header is set before each call."],"tags":["fastapi","authentication","http-headers","httpexception"],"analyzedSha":"42a41db11f6882807ac3c057b942178d53b97438","analyzedAt":"2026-08-04T19:23:32.007Z","schemaVersion":2}