Chat socket closed unexpectedly

I am deploying my chat application on Heroku and facing error when trying to send message, I don’t know how to solve it. When I run code locally it works fine if instead of:

const chatSocket = new WebSocket(
      "wss://" + + "/ws/chat/" + roomName + "/"

I use:

const chatSocket = new WebSocket(
      "ws://" + + "/ws/chat/" + roomName + "/"

Error in console:

JavaScript in chatroom.html:

const roomName = JSON.parse(document.getElementById("room-name").textContent);
    const chatSocket = new WebSocket(
      "wss://" + + "/ws/chat/" + roomName + "/"

    chatSocket.onmessage = function (e) {
      const data = JSON.parse(;


    chatSocket.onclose = function (e) {
      console.error("Chat socket closed unexpectedly");

    document.querySelector("#chat-message-input").onkeyup = function (e) {
      if (e.keyCode === 13) {
        // enter, return

    document.querySelector("#chat-message-submit").onclick = function (e) {
      const messageInputDom = document.querySelector("#chat-message-input");
      const message = messageInputDom.value;
      const checkInput = message.replaceAll(/\s/g, "");
      if (!checkInput) return;
      chatSocket.onopen = () => {
            message: message,
      messageInputDom.value = "";

import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer

from .models import Messages

class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
        self.room_group_name = "chat_%s" % self.room_name  
        # Join room group
            self.room_group_name, self.channel_name

    def disconnect(self, close_code):
            self.room_group_name, self.channel_name

    # Receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]

        # Sender
        username = self.scope["user"].username
        finalMessage = (username + ': ' + message)
        # Save message in database
        Messages.objects.create(room_name = self.room_name, message = finalMessage)
            self.room_group_name, {"type": "chat_message", "message": finalMessage}

    # Receive message from room group
    def chat_message(self, event):
        message = event["message"]
        username = self.scope["user"].username
        self.send(text_data=json.dumps({'message': message,
        "username": username}))

import os
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
django_asgi_app = get_asgi_application()

from channels.auth import AuthMiddlewareStack
from import AllowedHostsOriginValidator
from anonymous.routing import websocket_urlpatterns

# Initialize Django ASGI application early to ensure the AppRegistry
# is populated before importing code that may import ORM models.

application = ProtocolTypeRouter(
        "http": django_asgi_app,
        "websocket": AllowedHostsOriginValidator(

What asgi container are you using for this? Daphne? What is your Daphne command line?
Do you have HTTPS working on your regular Django application?

This is daphne I used in Proc file to deploy on Heroku daphne -b -p 8001 core.asgi:application
When I run website on local everything works perfectly, I tested it. No bugs or any errors occurred while sending a message or doing any other acction.

You pointed out that you made a change. You switched from this:

to this:

which means you’re now trying to use a websocket with ssl. And that means that your server needs to be configured for ssl usage.

I don’t know anything about heroku here, so you’re going to need to find their docs to figure out how to configure it for ssl. (Also, I notice you’re not specifying a port number for the connection, so I’m guessing you’ve got some type of configuration file defined to forward port 443 to 8001.)

Thanks for the help, this clears up a lot to me. I have one question, what are you using to host your web applications?

I use complete server images - either self-hosted or services such as AWS EC2 and Linode. That way I have complete control over the configurations for docker, nginx, PostgreSQL, redis, postfix, celery, cron, uwsgi and/or Daphne, etc, etc, etc. Also, I do a fair amount of work on internal-only systems, where deployment to an external host wouldn’t work. About a quarter of the projects I work on get deployed to environments that don’t even have internet access.

1 Like

Okay, thanks for the insight. I will research those.

Here is what solved my problem:

In Procfile I needed to use this:
web: daphne core.asgi:application --port $PORT --bind -v2
Instead of this:
web: gunicorn core.wsgi --log-file -

Because obviously, I needed to run the ASGI server, it was a dumb mistake I overlooked. Also, I added this part in my chartroom.html:

let wsStart = "ws://";
    if (window.location.protocol == "https:") {
      wsStart = "wss://";

const chatSocket = new WebSocket(wsStart + + "/ws/chat/" + roomName + "/");

This part automatically checks if there is HTTPS and configures the web socket accordingly so it uses WSS and not WS.