Troubleshooting

This page lists common problems when using Django-AWS-API-Gateway-WebSockets and how to investigate them.

General checklist

If something is not working, start with this checklist:

  • the Django application is reachable over HTTPS;

  • the API Gateway has been created and deployed;

  • the API Gateway record in Django has the expected API ID;

  • the target base endpoint is correct and ends with a trailing slash;

  • the Django URL includes <slug:route>;

  • the slug parameter is named route;

  • AWS credentials are configured correctly;

  • IAM permissions allow the action you are trying to perform;

  • DNS points to the correct API Gateway domain;

  • the browser is connecting with wss://;

  • WebSocket tokens are configured correctly if enabled;

  • old sessions, tokens, and rate limit records are being cleaned up.

Connection fails immediately

Symptoms

The browser cannot open the WebSocket connection.

You may see errors such as:

WebSocket connection failed

or:

Error during WebSocket handshake

Possible causes

Common causes include:

  • incorrect WebSocket URL;

  • using https:// instead of wss://;

  • DNS not pointing to API Gateway;

  • custom domain not configured correctly;

  • certificate not valid;

  • API Gateway stage not deployed;

  • Django endpoint not reachable from API Gateway;

  • missing or invalid WebSocket token;

  • API Gateway routes not configured.

What to check

Check that the browser connects to a WebSocket URL:

wss://ws.example.com

not:

https://ws.example.com

Check that the custom domain resolves correctly.

Check that the API Gateway record has been created and deployed.

Check that API Gateway can reach your Django endpoint over HTTPS.

Django returns bad request

Symptoms

The connection reaches Django, but Django rejects it with a bad request.

Possible causes

Common causes include:

  • missing expected headers;

  • request did not come through API Gateway;

  • invalid host or origin;

  • invalid connection ID;

  • invalid channel name;

  • missing token;

  • expired token;

  • reused token;

  • route parameter is missing or misnamed.

What to check

Confirm that your Django URL pattern contains a slug named route.

path(
    "ws/<slug:route>",
    ExampleWebSocketView.as_view(),
    name="example_websocket",
)

The parameter must be named route.

If using a local tunnel or proxy, check whether expected headers are being removed or rewritten.

Messages always go to the default handler

Symptoms

Custom handlers are not called. All messages are handled by default.

Possible causes

Common causes include:

  • the client payload does not include the expected handler or action key;

  • the API Gateway route selection expression does not match the payload;

  • the Django view uses a different handler selection key;

  • the custom handler is not included in allowed handlers;

  • the method name does not match the requested handler name;

  • the handler name contains characters that are not valid for a Python method.

What to check

Check the client payload.

socket.send(JSON.stringify({
    action: "chat_message",
    message: "Hello"
}));

Check that the Django view has a matching method.

def chat_message(self, request, *args, **kwargs):
    return None

If using explicit handler whitelisting, check that the handler is allowed.

ALLOWED_HANDLERS = {
    "default",
    "chat_message",
}

Custom route is not called

Symptoms

A custom API Gateway route does not call the expected Django view.

Possible causes

Common causes include:

  • the custom route has not been created;

  • the API Gateway has not been redeployed;

  • the route key does not match the client payload;

  • the additional route integration URL is wrong;

  • the target Django URL is not reachable;

  • the route selection expression does not match your message shape.

What to check

Confirm that the additional route exists in AWS API Gateway.

Confirm that the API Gateway stage has been redeployed.

Confirm that the client sends the expected route key.

socket.send(JSON.stringify({
    action: "notifications",
    message: "Hello"
}));

Confirm that the route key is notifications if that is the route you expect.

WebSocket token request fails

Symptoms

The browser cannot get a WebSocket token.

The token endpoint may return 403 Forbidden.

Possible causes

Common causes include:

  • user is not authenticated;

  • CSRF token is missing;

  • CSRF token is invalid;

  • session cookie is missing;

  • token generation rate limit has been exceeded;

  • token endpoint URL is wrong;

  • cookies are not being sent with the request.

What to check

Make sure the request includes:

  • X-CSRFToken header;

  • Django session cookie;

  • credentials: "same-origin" in the fetch request.

Example:

const response = await fetch("/api/ws-token/", {
    method: "POST",
    headers: {
        "X-CSRFToken": csrfToken,
        "Content-Type": "application/json"
    },
    credentials: "same-origin"
});

See WebSocket tokens.

WebSocket token is rejected during connection

Symptoms

The token request succeeds, but the WebSocket connection is rejected.

Possible causes

Common causes include:

  • token was not included in the WebSocket URL;

  • token expired before the connection was opened;

  • token was already used;

  • reconnect attempted to reuse an old token;

  • session cookie changed between token request and connection;

  • connection is opened from a different browser context.

What to check

Check that the URL includes ws_token.

wss://ws.example.com?ws_token=<token>&channel=notifications

Request the token immediately before opening the WebSocket connection.

For reconnects, always request a fresh token.

Rate limit exceeded

Symptoms

Connections or token requests are rejected after repeated attempts.

Possible causes

Common causes include:

  • reconnect loop is too aggressive;

  • frontend repeatedly requests tokens;

  • multiple tabs are open;

  • connection attempts are failing and retrying rapidly;

  • legitimate usage exceeds the configured limits;

  • abuse or automated traffic.

What to check

Check the reconnect settings in the browser.

Avoid rapid reconnect loops.

If using reconnecting-websocket, use backoff settings.

const socket = new ReconnectingWebSocket(websocketUrl, null, {
    debug: false,
    reconnectInterval: 3000,
    maxReconnectInterval: 10000,
    reconnectDecay: 1.5,
    timeoutInterval: 5000,
    maxReconnectAttempts: null
});

If legitimate clients are being limited, adjust the view settings.

class ExampleWebSocketView(WebSocketView):
    RATE_LIMIT_ENABLED = True
    RATE_LIMIT_MAX_ATTEMPTS = 40
    RATE_LIMIT_WINDOW_MINUTES = 5

See Rate limiting.

User is anonymous unexpectedly

Symptoms

The WebSocket view receives an anonymous user when an authenticated user was expected.

Possible causes

Common causes include:

  • WebSocket token protection is disabled;

  • token request was made anonymously;

  • session cookie is not available to the WebSocket endpoint;

  • cookie domain does not cover the WebSocket subdomain;

  • session expired;

  • user logged out before connecting;

  • custom domain setup uses a different parent domain.

What to check

If your site is:

https://www.example.com

and your WebSocket endpoint is:

wss://ws.example.com

review your cookie settings.

You may need to configure:

  • SESSION_COOKIE_DOMAIN;

  • CSRF_COOKIE_DOMAIN;

  • CSRF_TRUSTED_ORIGINS;

  • SESSION_COOKIE_SAMESITE;

  • CSRF_COOKIE_SAMESITE.

See Configuration and API Gateway Setup.

Permission denied

Symptoms

The connection works, but a message handler returns permission denied.

Possible causes

Common causes include:

  • user does not have the required Django permission;

  • view-level permissions are too strict;

  • handler-level permission check fails;

  • user is connected to a channel they cannot access;

  • object-level access check fails.

What to check

Check the user’s Django permissions.

Check the view configuration.

class ExampleWebSocketView(WebSocketView):
    permissions_required = [
        "chat.can_use_chat",
    ]

For object-level access, check your handler logic.

See Permissions.

Messages are not received by the browser

Symptoms

Django sends a message, but the browser does not receive it.

Possible causes

Common causes include:

  • the connection is no longer active;

  • the message was sent to the wrong channel;

  • the session has connected=False;

  • stale session records exist;

  • AWS returned a gone connection response;

  • the browser’s onmessage handler has an error;

  • the message is not valid JSON for your frontend handler;

  • the user changed rooms and is now on another channel.

What to check

Check that the queryset targets the expected channel.

WebSocketSession.objects.filter(
    channel_name="general",
).send_message(
    {
        "type": "chat_message",
        "message": "Hello",
    }
)

Check the browser console for JavaScript errors.

Check that stale sessions are being cleaned up.

See Clean-up.

GoneException when sending messages

Symptoms

AWS reports that a connection has gone away when Django tries to send a message.

Possible causes

This usually means the client is no longer connected.

Common causes include:

  • browser tab was closed;

  • network disconnected;

  • API Gateway timed out the connection;

  • client changed rooms;

  • stale session still exists in the database.

What to check

Treat gone connections as normal operational behaviour.

Make sure cleanup is scheduled.

See Clean-up.

Messages fail because they are too large

Symptoms

Sending a message fails when the payload is large.

Possible causes

AWS API Gateway WebSocket messages have size limits.

What to check

Keep WebSocket messages small.

For large payloads, send a lightweight notification and let the browser fetch the full data over HTTPS.

Example:

{
  "type": "report_ready",
  "report_id": 123,
  "fetch_url": "/reports/123/"
}

Local development does not work

Symptoms

The application works in production but not locally, or API Gateway cannot reach the local Django server.

Possible causes

Common causes include:

  • local server is not publicly reachable;

  • local server is not using HTTPS;

  • tunnel URL changed;

  • API Gateway target endpoint still points to an old URL;

  • tunnel strips or rewrites headers;

  • Django ALLOWED_HOSTS does not include the tunnel host.

What to check

Use a tunnelling service to expose your local server over HTTPS.

Update the API Gateway target base endpoint to the tunnel URL.

Check ALLOWED_HOSTS and CSRF settings.

See Local development.

Custom domain does not work

Symptoms

The generated API Gateway endpoint works, but the custom domain does not.

Possible causes

Common causes include:

  • certificate is not validated;

  • certificate does not cover the WebSocket domain;

  • DNS record points to the wrong target;

  • API mapping was not created;

  • custom domain is in the wrong AWS region;

  • stage mapping is incorrect.

What to check

Check the API Gateway record for the API Gateway domain name.

Check your DNS provider.

Check the certificate in AWS Certificate Manager.

Check that the custom domain is mapped to the expected API and stage.

API Gateway creation fails

Symptoms

The admin action or management command fails when creating API Gateway resources.

Possible causes

Common causes include:

  • missing IAM permissions;

  • incorrect AWS region;

  • invalid target base endpoint;

  • invalid certificate ARN;

  • invalid domain name;

  • AWS service-linked role permission issue;

  • credentials are not available to Django.

What to check

Check AWS credentials.

Check the configured AWS region.

Check the IAM policy.

See AWS IAM Setup.

Management command cannot send or create resources

Symptoms

Management commands fail locally or in deployment.

Possible causes

Common causes include:

  • virtual environment is not active;

  • Django settings module is not configured;

  • AWS credentials are missing;

  • wrong AWS profile is selected;

  • IAM permissions are insufficient;

  • command arguments are incorrect.

What to check

Check that you can run normal Django commands first.

Check the configured AWS credential method.

Check the primary key passed to API Gateway commands.

Example:

python manage.py createApiGateway --pk=1

Debugging WebSocket views

You can enable debug behaviour on the view during development.

Example:

path(
    "ws/<slug:route>",
    ExampleWebSocketView.as_view(debug=True),
    name="example_websocket",
)

Do not expose detailed debugging information to users in production.

Cleanup problems

Symptoms

The database contains many old sessions, tokens, or rate limit records.

Possible causes

Common causes include:

  • cleanup commands are not scheduled;

  • scheduled task is using the wrong environment;

  • command name or arguments are wrong;

  • task runner cannot access the Django project;

  • stale sessions are expected but not being pruned.

What to check

Run cleanup manually first.

python manage.py clearWebSocketSessions
python manage.py cleanupWebSocketTokens --token-age=300 --rate-limit-age=7

Then schedule the commands using cron, Celery Beat, a container scheduler, or your platform’s scheduled task system.

See Clean-up.

Getting more information

When debugging, collect:

  • browser console errors;

  • browser network WebSocket details;

  • API Gateway logs;

  • Django logs;

  • API Gateway record values;

  • WebSocket session records;

  • token records;

  • rate limit records;

  • AWS region and account details;

  • custom domain and DNS values.