{"record":{"id":"081f977b85d7c8fa","repo":"tiangolo/fastapi","slug":"x-key-header-invalid-081f97","errorCode":null,"errorMessage":"X-Key header invalid","messagePattern":"X-Key header invalid","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"docs_src/dependencies/tutorial012_an_py310.py","lineNumber":13,"sourceCode":"from typing import Annotated\n\nfrom fastapi import Depends, FastAPI, Header, HTTPException\n\n\nasync def verify_token(x_token: Annotated[str, Header()]):\n    if x_token != \"fake-super-secret-token\":\n        raise HTTPException(status_code=400, detail=\"X-Token header invalid\")\n\n\nasync def verify_key(x_key: Annotated[str, Header()]):\n    if x_key != \"fake-super-secret-key\":\n        raise HTTPException(status_code=400, detail=\"X-Key header invalid\")\n    return x_key\n\n\napp = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])\n\n\n@app.get(\"/items/\")\nasync def read_items():\n    return [{\"item\": \"Portal Gun\"}, {\"item\": \"Plumbus\"}]\n\n\n@app.get(\"/users/\")\nasync def read_users():\n    return [{\"username\": \"Rick\"}, {\"username\": \"Morty\"}]\n","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/docs_src/dependencies/tutorial012_an_py310.py#L1-L28","documentation":"HTTPException (400) from the global dependency verify_key, the second app-level dependency. It validates the X-Key header against 'fake-super-secret-key' and returns the key on success. Every route on the app requires both X-Token and X-Key; X-Key failing produces this 400.","triggerScenarios":"Any request to a route on this app where X-Token is valid but X-Key is missing or != 'fake-super-secret-key'. Note: because both dependencies are declared, a missing X-Key yields a 422 first; a present-but-wrong X-Key yields this 400.","commonSituations":"Multi-header API-gateway checks. Developers pass X-Token correctly but forget X-Key, or send a stale key after rotation.","solutions":["Send header X-Key: fake-super-secret-key on every request (in addition to a valid X-Token).","Confirm both headers are present and correctly named; FastAPI parameter x_key maps to header 'X-Key'.","Centralize secret retrieval so X-Token and X-Key are configured together and cannot drift."],"exampleFix":"// before\ncurl -H 'X-Token: fake-super-secret-token' http://localhost:8000/items/\n// after\ncurl -H 'X-Token: fake-super-secret-token' -H 'X-Key: fake-super-secret-key' http://localhost:8000/items/","handlingStrategy":"validation","validationCode":"headers = {'X-Token': 'fake-super-secret-token', 'X-Key': os.environ.get('X_KEY', 'fake-super-secret-key')}\nassert headers['X-Key']","typeGuard":"def has_valid_x_key(headers: dict) -> bool:\n    return headers.get('X-Key') == 'fake-super-secret-key'","tryCatchPattern":"resp = requests.get('http://localhost:8000/items/', headers=headers)\nif resp.status_code == 400 and 'X-Key' in resp.text:\n    print('bad/missing X-Key')","preventionTips":["Always send both required headers together.","Rotate both secrets in lockstep.","Add a client interceptor to inject auth headers on every call."],"tags":["fastapi","http-400","headers","authentication","global-dependency"],"backgroundTag":null,"analyzedSha":"3e8d1526d83a90aaf7d6eb6dc682bf150f180b25","analyzedAt":"2026-08-11T02:34:52.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}