{"record":{"id":"aeae7ed34e07c0af","repo":"tiangolo/fastapi","slug":"sse-field-name-must-be-a-single-line","errorCode":null,"errorMessage":"SSE '{field_name}' must be a single line","messagePattern":"SSE '(.+?)' must be a single line","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastapi/sse.py","lineNumber":38,"sourceCode":"class EventSourceResponse(StreamingResponse):\n    \"\"\"Streaming response with `text/event-stream` media type.\n\n    Use as `response_class=EventSourceResponse` on a *path operation* that uses `yield`\n    to enable Server Sent Events (SSE) responses.\n\n    Works with **any HTTP method** (`GET`, `POST`, etc.), which makes it compatible\n    with protocols like MCP that stream SSE over `POST`.\n\n    The actual encoding logic lives in the FastAPI routing layer. This class\n    serves mainly as a marker and sets the correct `Content-Type`.\n    \"\"\"\n\n    media_type = \"text/event-stream\"\n\n\ndef _check_single_line(v: str | None, field_name: str) -> str | None:\n    if v is not None and (\"\\r\" in v or \"\\n\" in v):\n        raise ValueError(f\"SSE '{field_name}' must be a single line\")\n    return v\n\n\ndef _check_event_single_line(v: str | None) -> str | None:\n    return _check_single_line(v, \"event\")\n\n\ndef _check_id_valid(v: str | None) -> str | None:\n    if v is not None and \"\\0\" in v:\n        raise ValueError(\"SSE 'id' must not contain null characters\")\n    return _check_single_line(v, \"id\")\n\n\nclass ServerSentEvent(BaseModel):\n    \"\"\"Represents a single Server-Sent Event.\n\n    When `yield`ed from a *path operation function* that uses\n    `response_class=EventSourceResponse`, each `ServerSentEvent` is encoded","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/fastapi/sse.py#L20-L56","documentation":"Raised by `_check_single_line` (fastapi/sse.py:38) as a ValueError when an SSE field ('event', 'id', or other single-line field) contains a carriage return ('\\r') or newline ('\\n'). The SSE wire format uses newlines as field delimiters, so an embedded newline would corrupt the stream by splitting one event into multiple fields. The validator is attached via `AfterValidator` to the `event` and `id` fields of `ServerSentEvent`.","triggerScenarios":"Constructing `ServerSentEvent(event='update\\nmore', data=...)` or `ServerSentEvent(id='abc\\ndef')`. Yielding an event whose `event`/`id` was built from user input that contains a newline. Multi-line strings assigned to `event` or `id`.","commonSituations":"Passing untrusted/user-controlled strings into `event` or `id` without sanitization. Building event names from concatenated values that introduced a '\\n'. Copying log lines (which contain newlines) into an SSE field.","solutions":["Sanitize the value: strip/replace line terminators before assignment, e.g. `event=event.replace('\\r', '').replace('\\n', ' ')`.","Use multiple `ServerSentEvent` yields for logically separate lines instead of embedding newlines.","Validate input upstream: reject or truncate strings containing '\\n'/'\\r' before constructing the event."],"exampleFix":"// before\nyield ServerSentEvent(event='update\\nrestart', data=payload)\n// after\nevent_name = 'update restart' if '\\n' in raw else raw\nyield ServerSentEvent(event=event_name.replace('\\n', ' '), data=payload)","handlingStrategy":"validation","validationCode":"from fastapi.sse import ServerSentEvent\n\ndef safe_event(event: str | None = None, **kw) -> ServerSentEvent:\n    if event is not None:\n        event = event.replace('\\r', '').replace('\\n', ' ')\n    return ServerSentEvent(event=event, **kw)","typeGuard":"def is_single_line(value: object) -> bool:\n    return isinstance(value, str) and '\\r' not in value and '\\n' not in value","tryCatchPattern":null,"preventionTips":["Sanitize any user-controlled string before assigning to event/id.","Unit-test SSE event construction with inputs containing newlines.","Treat event/id fields as opaque tokens, not free 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"}