Skip to main content

WebSocket Specific Errors

To manage errors in WebSocket connections, FastAPI provides specialized exception classes that trigger connection closures with specific status codes instead of returning standard HTTP responses.

Manually Closing Connections with WebSocketException

When you need to reject a connection or terminate a session due to business logic (such as failed authentication or invalid permissions), raise a WebSocketException. This class extends Starlette's version and allows you to specify a closing code and an optional reason.

If you raise this exception before calling await websocket.accept(), FastAPI will reject the connection with the provided code.

from typing import Annotated
from fastapi import (
Cookie,
FastAPI,
WebSocket,
WebSocketException,
status,
)

app = FastAPI()

@app.websocket("/items/{item_id}/ws")
async def websocket_endpoint(
*,
websocket: WebSocket,
session: Annotated[str | None, Cookie()] = None,
item_id: str,
):
# Check for a session cookie before accepting the connection
if session is None:
raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION, reason="Session cookie missing")

await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}")

Handling Automatic Validation Errors

FastAPI automatically raises a WebSocketRequestValidationError when the parameters defined in your WebSocket endpoint (like Query, Header, or Cookie dependencies) fail validation.

By default, FastAPI uses the websocket_request_validation_exception_handler found in fastapi/exception_handlers.py. This handler closes the connection using the code 1008 (WS_1008_POLICY_VIOLATION) and sends the validation error details as the closure reason.

# Internal default behavior in fastapi/exception_handlers.py
async def websocket_request_validation_exception_handler(
websocket: WebSocket, exc: WebSocketRequestValidationError
) -> None:
await websocket.close(
code=WS_1008_POLICY_VIOLATION, reason=jsonable_encoder(exc.errors())
)

Customizing WebSocket Validation Handlers

You can override the default behavior for validation errors by registering a custom exception handler for WebSocketRequestValidationError. This is useful if you want to log errors or change the closure code.

from fastapi import FastAPI, WebSocket, status
from fastapi.exceptions import WebSocketRequestValidationError
from fastapi.encoders import jsonable_encoder

app = FastAPI()

@app.exception_handler(WebSocketRequestValidationError)
async def custom_websocket_validation_handler(
websocket: WebSocket, exc: WebSocketRequestValidationError
):
# Access detailed error info via exc.errors()
# Access endpoint context (like function name) via exc.endpoint_ctx
await websocket.close(
code=status.WS_1003_UNSUPPORTED_DATA,
reason=jsonable_encoder(exc.errors())
)

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, q: int): # q must be an integer
await websocket.accept()
await websocket.send_text(f"Query param q is: {q}")

Accessing Endpoint Context

The WebSocketRequestValidationError includes an endpoint_ctx attribute. This provides metadata about the endpoint where the error occurred, which can be useful for centralized logging or debugging.

@app.exception_handler(WebSocketRequestValidationError)
async def logging_handler(websocket: WebSocket, exc: WebSocketRequestValidationError):
if exc.endpoint_ctx:
print(f"Validation failed in: {exc.endpoint_ctx.endpoint.__name__}")
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)

Troubleshooting

Closure Before Accept

If you raise a WebSocketException or trigger a WebSocketRequestValidationError before calling await websocket.accept(), the client will receive a closure frame immediately. Some WebSocket clients might report this as a failed connection attempt rather than a clean closure with a code.

Reason String Limits

The reason parameter in WebSocketException and the close() method is UTF-8 encoded. While FastAPI uses jsonable_encoder to convert validation errors into a string for the reason, the WebSocket specification limits the length of the closure frame. If your validation errors are extremely large, the closure reason might be truncated or cause issues with certain client implementations.

Exception Middleware

WebSocket exceptions are caught by Starlette's ExceptionMiddleware. If you raise a standard HTTPException inside a WebSocket endpoint, it will not return a JSON response; instead, it will typically result in a connection closure with a generic error code (usually 1011 Internal Error) because HTTP responses cannot be sent over a WebSocket protocol once the handshake is initiated. Always use WebSocketException for logic errors within WebSocket routes.