{"record":{"id":"0aa9b7ff7955b8f0","repo":"tiangolo/fastapi","slug":"cannot-set-both-data-and-raw-data-on-the-same","errorCode":null,"errorMessage":"Cannot set both 'data' and 'raw_data' on the same ServerSentEvent. Use 'data' for JSON-serialized payloads or 'raw_data' for pre-formatted strings.","messagePattern":"Cannot set both 'data' and 'raw_data' on the same ServerSentEvent\\. Use 'data' for JSON-serialized payloads or 'raw_data' for pre-formatted strings\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastapi/sse.py","lineNumber":151,"sourceCode":"        ),\n    ] = None\n    comment: Annotated[\n        str | None,\n        Doc(\n            \"\"\"\n            Optional comment line(s).\n\n            Comment lines start with `:` in the SSE wire format and are ignored by\n            `EventSource` clients. Useful for keep-alive pings to prevent\n            proxy/load-balancer timeouts.\n            \"\"\"\n        ),\n    ] = None\n\n    @model_validator(mode=\"after\")\n    def _check_data_exclusive(self) -> \"ServerSentEvent\":\n        if self.data is not None and self.raw_data is not None:\n            raise ValueError(\n                \"Cannot set both 'data' and 'raw_data' on the same \"\n                \"ServerSentEvent. Use 'data' for JSON-serialized payloads \"\n                \"or 'raw_data' for pre-formatted strings.\"\n            )\n        return self\n\n\ndef _split_sse_lines(value: str) -> list[str]:\n    # Split on SSE-spec line terminators only (\\n, \\r\\n, \\r), preserving\n    # trailing empty strings.\n    return value.replace(\"\\r\\n\", \"\\n\").replace(\"\\r\", \"\\n\").split(\"\\n\")\n\n\ndef format_sse_event(\n    *,\n    data_str: Annotated[\n        str | None,\n        Doc(","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/fastapi/sse.py#L133-L169","documentation":"Raised by `ServerSentEvent._check_data_exclusive` (fastapi/sse.py:151, a `model_validator(mode='after')`) as a ValueError when both `data` and `raw_data` are set on the same `ServerSentEvent`. They are mutually exclusive: `data` is always JSON-serialized, `raw_data` is sent verbatim as the `data:` field. Setting both is ambiguous, so FastAPI rejects it at model validation time.","triggerScenarios":"Constructing `ServerSentEvent(data={'k': 1}, raw_data='hello')`. Passing both keys in a dict: `ServerSentEvent(**{'data': x, 'raw_data': y})`. Building events generically and accidentally populating both fields.","commonSituations":"Generic event builders that accept both options. Migrating from `raw_data` to `data` (or vice versa) and forgetting to clear the old field. Copy-paste from an example that set one, then overriding the other.","solutions":["Use only `data` when you want JSON serialization: `ServerSentEvent(data=payload)`.","Use only `raw_data` when you want the string verbatim: `ServerSentEvent(raw_data=text)`.","In generic builders, branch on input type and set exactly one of the two fields."],"exampleFix":"// before\nyield ServerSentEvent(data={'msg': 'hi'}, raw_data='hi')\n// after\nyield ServerSentEvent(data={'msg': 'hi'})","handlingStrategy":"type-guard","validationCode":"from fastapi.sse import ServerSentEvent\n\ndef build_event(*, data=None, raw_data=None, **kw) -> ServerSentEvent:\n    if data is not None and raw_data is not None:\n        raise ValueError('pass exactly one of data or raw_data')\n    return ServerSentEvent(data=data, raw_data=raw_data, **kw)","typeGuard":"def exactly_one_payload(data, raw_data) -> bool:\n    return (data is not None) ^ (raw_data is not None)","tryCatchPattern":null,"preventionTips":["Branch in generic builders: choose data XOR raw_data based on input type.","Use mypy to flag code paths that could set both fields.","Prefer data for structured payloads; reserve raw_data for pre-formatted text."],"tags":["fastapi","sse","validation","streaming"],"backgroundTag":null,"analyzedSha":"3e8d1526d83a90aaf7d6eb6dc682bf150f180b25","analyzedAt":"2026-08-11T02:34:52.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}