Error during self.channel_layer.group_add

I have a Django application that has been deployed to a customer for about a year. The application is deployed with an Apache web server. They recently asked for a simple chat window to be added. I have implemented this with channels and Daphne. It works just fine in my development environment (i.e. python manage.py runserver) using both the in memory and redis back ends. Now I’m trying to get it to work in a production environment. I am still using Apache with it forwarding web socket to Daphne. As far as I can tell I also need to install the redis-server. I have done this and have it configured to run under systemd. I have the chat window working as expected using the in memory back end and am now trying to get it to work using the redis back end. Unfortunately I get this error from the Daphne service (i.e. journalctl -xeu daphne.service).

Mar 25 15:43:35 Stout daphne[1877778]: ChatConsumer:connect channel: specific.1c104be543f142c7a794544f1a401a72!2ed22171937340609b8a4c49e9fe8462
Mar 25 15:43:35 Stout daphne[1877778]: ChatConsumer:connect, add group: chat to channel specific.1c104be543f142c7a794544f1a401a72!2ed22171937340609b8a4c49e9fe8462
Mar 25 15:43:36 Stout daphne[1877778]: 2026-03-25 15:43:36,438 ERROR    Exception inside application: label empty or too long
Mar 25 15:43:36 Stout daphne[1877778]: Traceback (most recent call last):
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/redis/asyncio/connection.py”, line 307, in connect_check_health
Mar 25 15:43:36 Stout daphne[1877778]:     await self.retry.call_with_retry(
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/redis/asyncio/retry.py”, line 50, in call_with_retry
Mar 25 15:43:36 Stout daphne[1877778]:     return await do()
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/redis/asyncio/connection.py”, line 768, in _connect
Mar 25 15:43:36 Stout daphne[1877778]:     reader, writer = await asyncio.open_connection(
Mar 25 15:43:36 Stout daphne[1877778]:                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/usr/lib/python3.12/asyncio/streams.py”, line 48, in open_connection
Mar 25 15:43:36 Stout daphne[1877778]:     transport, _ = await loop.create_connection(
Mar 25 15:43:36 Stout daphne[1877778]:                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/usr/lib/python3.12/asyncio/base_events.py”, line 1080, in create_connection
Mar 25 15:43:36 Stout daphne[1877778]:     infos = await self._ensure_resolved(
Mar 25 15:43:36 Stout daphne[1877778]:             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/usr/lib/python3.12/asyncio/base_events.py”, line 1456, in _ensure_resolved
Mar 25 15:43:36 Stout daphne[1877778]:     return await loop.getaddrinfo(host, port, family=family, type=type,
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/usr/lib/python3.12/asyncio/base_events.py”, line 901, in getaddrinfo
Mar 25 15:43:36 Stout daphne[1877778]:     return await self.run_in_executor(
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/usr/lib/python3.12/concurrent/futures/thread.py”, line 58, in run
Mar 25 15:43:36 Stout daphne[1877778]:     result = self.fn(*self.args, **self.kwargs)
Mar 25 15:43:36 Stout daphne[1877778]:              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/usr/lib/python3.12/socket.py”, line 963, in getaddrinfo
Mar 25 15:43:36 Stout daphne[1877778]:     for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
Mar 25 15:43:36 Stout daphne[1877778]:                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/usr/lib/python3.12/encodings/idna.py”, line 173, in encode
Mar 25 15:43:36 Stout daphne[1877778]:     raise UnicodeError(“label empty or too long”)
Mar 25 15:43:36 Stout daphne[1877778]: UnicodeError: label empty or too long
Mar 25 15:43:36 Stout daphne[1877778]: encoding with ‘idna’ codec failed
Mar 25 15:43:36 Stout daphne[1877778]: The above exception was the direct cause of the following exception:
Mar 25 15:43:36 Stout daphne[1877778]: Traceback (most recent call last):
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/routing.py”, line 48, in call
Mar 25 15:43:36 Stout daphne[1877778]:     return await application(scope, receive, send)
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/sessions.py”, line 44, in call
Mar 25 15:43:36 Stout daphne[1877778]:     return await self.inner(dict(scope, cookies=cookies), receive, send)
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/sessions.py”, line 261, in call
Mar 25 15:43:36 Stout daphne[1877778]:     return await self.inner(wrapper.scope, receive, wrapper.send)
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/auth.py”, line 185, in call
Mar 25 15:43:36 Stout daphne[1877778]:     return await super().call(scope, receive, send)
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/middleware.py”, line 24, in call
Mar 25 15:43:36 Stout daphne[1877778]:     return await self.inner(scope, receive, send)
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/routing.py”, line 118, in call
Mar 25 15:43:36 Stout daphne[1877778]:     return await application(
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/consumer.py”, line 95, in app
Mar 25 15:43:36 Stout daphne[1877778]:     return await consumer(scope, receive, send)
Mar 25 15:43:36 Stout daphne[1877778]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/consumer.py”, line 58, in call
Mar 25 15:43:36 Stout daphne[1877778]:     await await_many_dispatch(
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/utils.py”, line 50, in await_many_dispatch
Mar 25 15:43:36 Stout daphne[1877778]:     await dispatch(result)
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/consumer.py”, line 74, in dispatch
Mar 25 15:43:36 Stout daphne[1877778]:     await handler(message)
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels/generic/websocket.py”, line 180, in websocket_connect
Mar 25 15:43:36 Stout daphne[1877778]:     await self.connect()
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/CSRMedical/medical/patients/consumers.py”, line 15, in connect
Mar 25 15:43:36 Stout daphne[1877778]:     await self.channel_layer.group_add(
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/channels_redis/core.py”, line 493, in group_add
Mar 25 15:43:36 Stout daphne[1877778]:     await connection.zadd(group_key, {channel: time.time()})
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/redis/asyncio/client.py”, line 720, in execute_command
Mar 25 15:43:36 Stout daphne[1877778]:     conn = self.connection or await pool.get_connection()
Mar 25 15:43:36 Stout daphne[1877778]:                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/redis/asyncio/connection.py”, line 1198, in get_connection
Mar 25 15:43:36 Stout daphne[1877778]:     await self.ensure_connection(connection)
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/redis/asyncio/connection.py”, line 1231, in ensure_connection
Mar 25 15:43:36 Stout daphne[1877778]:     await connection.connect()
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/redis/asyncio/connection.py”, line 298, in connect
Mar 25 15:43:36 Stout daphne[1877778]:     await self.connect_check_health(check_health=True)
Mar 25 15:43:36 Stout daphne[1877778]:   File “/home/csrmedical/venv/lib/python3.12/site-packages/redis/asyncio/connection.py”, line 319, in connect_check_health
Mar 25 15:43:36 Stout daphne[1877778]:     raise ConnectionError(exc) from exc
Mar 25 15:43:36 Stout daphne[1877778]: redis.exceptions.ConnectionError: label empty or too long


Here is my consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from datetime import datetime
import logging

logger = logging.getLogger('app')

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_group_name = 'chat'
        logger.debug(f'ChatConsumer:connect channel: {self.channel_name}')

        # Join chat group
        logger.debug(f'ChatConsumer:connect, add group: {self.room_group_name} to channel {self.channel_name}')
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        logger.debug(f'ChatConsumer:connect, await accept')
        await self.accept()
        logger.debug(f'ChatConsumer:connect, accept complete')

    async def disconnect(self, close_code):
        # Leave chat group
        logger.debug(f'ChatConsumer:disconnect channel: {self.channel_name}')
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        logger.debug(f'ChatConsumer:recieve channel: {self.channel_name}')
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        username = 'Anonymous'
        if self.scope['user'].is_authenticated :
            username = self.scope['user'].username

        logger.debug(f'ChatConsumer:recieve message: {message}, user: {username}')
        now = datetime.now().ctime()

        # Broadcast message to chat group
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message,
                'username': username,
                'date': now,
            }
        )

    async def chat_message(self, event):
        logger.debug(f'ChatConsumer:chat_message message: {event['message']}')
        message = event['message']
        username = event['username']
        now = event['date']
        await self.send(text_data=json.dumps({
            'message': message,
            'username': username,
            'date': now,
        }))

Based on my debug logging, the error is occurring in group_add, but I have no idea what label is empty or too long. It seems like I saw this at one time on my dev system, but have no idea how I fixed it. At this point, I’m not even sure what to look at. I assume it is a configuration error, but beyond that I’m at a loss. Any help is greatly appreciated.

Here is what I think are the relevant settings/configuration

CHANNEL_LAYERS from settings.py

"""
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer"
    }
}
"""
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("127.0.0.1", 6379)],
        }
    }
}

installed packages

asgiref==3.11.0
attrs==25.4.0
autobahn==25.12.2
Automat==25.4.16
cbor2==5.7.1
cffi==2.0.0
channels==4.3.2
channels_redis==4.3.0
constantly==23.10.4
cryptography==46.0.3
daphne==4.2.1
Django==6.0
django-redis==6.0.0
hyperlink==21.0.0
idna==3.11
Incremental==24.11.0
msgpack==1.1.2
packaging==25.0
py-ubjson==0.16.1
pyasn1==0.6.1
pyasn1_modules==0.4.2
pycparser==2.23
pyOpenSSL==25.3.0
redis==7.3.0
service-identity==24.2.0
sqlparse==0.5.5
Twisted==25.5.0
txaio==25.12.2
typing_extensions==4.15.0
ujson==5.11.0
zope.interface==8.1.1

I believe that the only change I made to the default redis.conf was to set supervised to auto.

Two quick things to check:

  • Ensure that you don’t have a second CHANNEL_LAYERS setting in your settings.py
  • Verify that redis is running, and that it’s the only process listening on port 6379.
1 Like

Try connecting to redis from the command line using redis-cli - that may help identify where the issue is.

Another thing to try - depending upon your OS and other system-configuration items you might have, you could try using “localhost” instead of “127.0.0.1”.

One more thing to try:

In the shell, run the following commands and report back what the results are:

(No output is expected from this first command)
import socket

socket.gethostname()

socket.getfqdn()

socket.getfqdn('127.0.0.1')

(Side note: I cribbed this from Encoding with 'idna' codec failed (UnicodeError: label empty or too long) - #12 by KenWhitesell)

1 Like

I only have the 2 CHANNEL_LAYERS configurations. The in memory configuration that is commented out and the redis configuration that is active.

2 Likes

I ran redis-cli and get a 127.0.0.1:6379> prompt. I assume that means it successfully connected to the redis server? I also did a successful PING.

2 Likes
socket.gethostname()

socket.getfqdn()

both return ‘Stout’, which is the hostname

socket.getfqdn('127.0.0.1')

returns ‘localhost’

I’ll try with localhost and Stout and see if I get different results.

2 Likes

OK dug a little deeper into the name resolution. It turns out localhost maps to 127.0.0.1 while Stout maps to 127.0.1.1. I’m not sure if that is expected or not. I’m running Ubuntu 24.04.3. From my experience I would have them both to be 127.0.0.1 or localhost to be 127.0.0.1 and Stout to be a network address (e.g. 192.168.1.75). In any case, localhost, 127.0.0.1, Stout, and 127.0.1.1 all generate the same label empty or too long error.

I also tried using redis-cli to connect to localhost, 127.0.0.1, Stout, and 127.0.1.1. It is able to connect to and pin localhost and 127.0.0.1. The connection fails with Stout and 127.0.1.1.

2 Likes

When you don’t have a fixed IP address, Ubuntu maps the hostname to 127.0.1.1. (See Chapter 5. Network setup)

Yes, that’s correct.

What are all the lines in your /etc/hosts file starting with 127?

Do you get this same error if you run daphne directly? (Not through systemd)

(If it works, please post the contents of your daphne service file.)

1 Like

When you don’t have a fixed IP address, Ubuntu maps the hostname to 127.0.1.1.

Nice to know. This is the first Linux system I’ve set up (first *ux in a looong time) and just used the default settings.

What are all the lines in your /etc/hosts file starting with 127?

127.0.0.1 localhost
127.0.1.1 Stout

There are also some IPv6 host mappings in /etc/hosts as well.

Do you get this same error if you run daphne directly?

No. I stopped the daphne service and then ran it from the command line via

/home/csrmedical/venv/bin/daphne -b 127.0.0.1 -p 8080 HouseUponTheRock.asgi:application

from a csrmedical login from the /home/csrmedical/CSRMedical/medical directory. It worked correctly. Here are the contents of my daphne.service file

[Unit]
Description=Daphne Service
After=network.target

[Service]
Type=simple
User=csrmedical
Group=www-data

WorkingDirectory=/home/csrmedical/CSRMedical/medical
ExecStart=/home/csrmedical/venv/bin/daphne -b 127.0.0.1 -p 8080 HouseUponTheRock.asgi:application

Restart=always

[Install]
WantedBy=multi-user.target

…and now I’m really confused. I noticed I was setting the group to www-data and thought I’d give it a try without setting the group so I changed daphne.service and restarted daphne and everything worked. Just to be sure that was the issue, I updated daphne.service to set the group again and restarted the daphne service and everything still worked. At this point I was confused and stopped daphne, redis, and apache then restarted them and everything continues to work as expected. I have no idea what the issue was initially but it seems to have fixed itself. Maybe something from when I ran daphne from the shell?

Thanks for your help.

1 Like

<conjecture>
Personally, that wouldn’t be my guess. I’d be more inclined to believe that the fix occured by editing the service file and reloading it in systemd. I’d say the root cause would more likely be a case where your After clause isn’t specific enough. Since you’re relying upon both redis and dns services, I’d want to make sure this starts after them.
</conjecture>