{"record":{"id":"2808e6f8434c339f","repo":"reflex-dev/reflex","slug":"missing-reflex-client-token-or-reflex-event-handle","errorCode":null,"errorMessage":"Missing reflex-client-token or reflex-event-handler header.","messagePattern":"Missing reflex-client-token or reflex-event-handler header\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/reflex-components-core/src/reflex_components_core/core/_upload.py","lineNumber":514,"sourceCode":"\n\ndef _require_upload_headers(request: Request) -> tuple[str, str]:\n    \"\"\"Extract the required upload headers from a request.\n\n    Args:\n        request: The incoming request.\n\n    Returns:\n        The client token and event handler name.\n\n    Raises:\n        HTTPException: If the upload headers are missing.\n    \"\"\"\n    token = request.headers.get(\"reflex-client-token\")\n    handler = request.headers.get(\"reflex-event-handler\")\n\n    if not token or not handler:\n        raise HTTPException(\n            status_code=400,\n            detail=\"Missing reflex-client-token or reflex-event-handler header.\",\n        )\n\n    return token, handler\n\n\n# Multipart form field carrying the JSON-encoded extra bound handler args.\n# Uploads travel over a REST endpoint instead of the socket, so args bound to\n# the handler (e.g. ``State.on_drop(rx.upload_files(...), field)``) ride in this\n# field. Kept in sync with the matching literal in the web upload template.\nUPLOAD_EVENT_ARGS_FIELD = \"__reflex_event_args\"\n\n# Cap on the buffered bound-args field for streaming uploads. The args are small\n# identifiers, so this only bounds the in-memory buffer against a hostile client\n# (file parts are backpressured via the chunk iterator; this field is not).\nMAX_UPLOAD_EVENT_ARGS_BYTES = 1024 * 1024\n","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/reflex-dev/reflex/blob/45b8ed5ab735f8a56bbb09a42384f030eb0208e7/packages/reflex-components-core/src/reflex_components_core/core/_upload.py#L496-L532","documentation":"The upload endpoint requires two headers to route and authorize a streaming upload: reflex-client-token (ties the upload to the client's state token) and reflex-event-handler (which handler to dispatch). Missing either yields HTTP 400 before parsing starts.","triggerScenarios":"POSTing to the upload URL without one or both of the reflex-client-token / reflex-event-handler headers — custom clients, curl tests, or proxies stripping custom headers.","commonSituations":"Custom upload scripts replicating the Reflex client; CORS proxies stripping custom X-/reflex- headers; older Reflex JS client version sending different header names after an upgrade.","solutions":["Include both headers: reflex-client-token: <token> and reflex-event-handler: <state.handler_name> in upload requests","Use rx.upload / the generated JS client which sets these automatically","Check proxy/CORS config allows and forwards the custom reflex-* headers"],"exampleFix":"# before\ncurl -X POST http://app/_upload -F files=@a.txt\n\n# after\ncurl -X POST http://app/_upload \\\n  -H 'reflex-client-token: <token>' \\\n  -H 'reflex-event-handler: state.handle_upload' \\\n  -F files=@a.txt","handlingStrategy":"validation","validationCode":"headers = {\"reflex-client-token\": token, \"reflex-event-handler\": handler}\nassert all(headers.values())","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the built-in Reflex upload client","Ensure proxies/CORS pass through reflex-* headers"],"tags":["upload","headers","http-400"],"backgroundTag":"missing-required-header","analyzedSha":"45b8ed5ab735f8a56bbb09a42384f030eb0208e7","analyzedAt":"2026-08-28T19:25:27.644Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}