Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Redis By James Joyner IV · · 8 min read

Redis Error Guide: 'BUSYGROUP Consumer Group name already exists' — Make Group Creation Idempotent

Fix BUSYGROUP Consumer Group name already exists in Redis Streams: understand XGROUP CREATE on restart, MKSTREAM, idempotent group setup, and safe consumer bootstrapping.

  • #redis
  • #troubleshooting
  • #errors
  • #streams

Overview

BUSYGROUP Consumer Group name already exists is returned by XGROUP CREATE when you try to create a consumer group on a Redis Stream that already has a group of that name. It is not a corruption or connectivity error — it means the group is already there, usually because your consumer bootstrap runs XGROUP CREATE unconditionally every time it starts.

The literal error clients receive:

(error) BUSYGROUP Consumer Group name already exists

This is the single most common “error” in Redis Streams applications, and it is almost always benign: the correct pattern is to ignore BUSYGROUP, because it simply confirms the group you wanted already exists. The fix is idempotent group creation, not any change to Redis itself.

Symptoms

  • XGROUP CREATE fails on service startup or on every worker boot.
  • The stream and group actually work fine once you skip the error.
  • Log noise of repeated BUSYGROUP on scale-up / redeploys.
redis-cli XGROUP CREATE orders g1 0
(error) BUSYGROUP Consumer Group name already exists
redis-cli XINFO GROUPS orders
1) 1) "name"
   2) "g1"
   3) "consumers"
   4) (integer) 3

Common Root Causes

1. Group already created (the normal case)

The service created the group on a previous boot; a later boot tries again.

redis-cli XINFO GROUPS orders | grep -A1 name
"name"
"g1"

The group’s presence is the cause — the create is simply redundant.

2. Multiple workers racing to create the same group

Several consumer instances start together; the first wins, the rest get BUSYGROUP.

redis-cli XINFO GROUPS orders
redis-cli CLIENT LIST | grep -c 'cmd=xgroup'

3. Non-idempotent bootstrap code

The startup path calls XGROUP CREATE without catching BUSYGROUP, so a normal restart surfaces as an error/crash.

# The safe form uses MKSTREAM and ignores BUSYGROUP
redis-cli XGROUP CREATE orders g1 '$' MKSTREAM

4. Confusion between recreating vs. resetting a group

You want to reset the group’s last-delivered ID, but XGROUP CREATE won’t do that on an existing group — you need XGROUP SETID.

redis-cli XINFO GROUPS orders | grep -A1 'last-delivered-id'

Diagnostic Workflow

Step 1: Confirm the group already exists

redis-cli XINFO GROUPS <stream>

Seeing your group name confirms BUSYGROUP is expected, not a fault.

Step 2: Inspect the stream and group state

redis-cli XINFO STREAM <stream>
redis-cli XINFO GROUPS <stream>
1) 1) "name"
   2) "g1"
   3) "last-delivered-id"
   4) "1720000000000-5"
   5) "pending"
   6) (integer) 12

Step 3: Check for pending / stuck messages

redis-cli XPENDING <stream> <group>
redis-cli XINFO CONSUMERS <stream> <group>
1) (integer) 12
2) "1720000000000-1"
3) "1720000000100-4"
4) 1) 1) "worker-2"
      2) "12"

Step 4: Verify the idempotent create pattern works

# This must NOT crash your app; catch BUSYGROUP and continue
redis-cli XGROUP CREATE <stream> <group> '$' MKSTREAM

Step 5: Check the log for how the app handled it

sudo journalctl -u myapp-consumer --no-pager | grep -iE 'BUSYGROUP|XGROUP' | tail

Example Root Cause Analysis

At 08:15 a deploy of the notifications consumer fails its readiness check. The container logs show it crashing on boot with BUSYGROUP Consumer Group name already exists returned from XGROUP CREATE notifications g1 0.

XINFO GROUPS confirms the group is perfectly healthy and already has consumers:

redis-cli XINFO GROUPS notifications
1) 1) "name"
   2) "g1"
   3) "consumers"
   4) (integer) 4
   5) "last-delivered-id"
   6) "1720003600000-2"

The root cause is purely client-side: the bootstrap treats a redundant XGROUP CREATE as fatal. On a first deploy the group did not exist and the create succeeded; on every deploy since, it correctly returns BUSYGROUP, which the code should swallow. The fix is idempotent group setup:

# Pseudocode bootstrap
try:
    XGROUP CREATE notifications g1 $ MKSTREAM
except error as e:
    if "BUSYGROUP" not in str(e):
        raise        # only re-raise real errors

Using MKSTREAM also removes the need to pre-create the stream, and catching BUSYGROUP makes restarts a no-op. After the change, deploys stop failing. If the intent had instead been to re-read from the top, the correct command would have been XGROUP SETID notifications g1 0, not a recreate.

Prevention Best Practices

  • Make group creation idempotent: run XGROUP CREATE ... MKSTREAM and catch/ignore BUSYGROUP — it means the group exists, which is what you want.
  • Use MKSTREAM so the stream is auto-created, avoiding a separate “stream not found” path.
  • To reset a group’s position, use XGROUP SETID (not recreate); to remove a stale consumer, use XGROUP DELCONSUMER.
  • Monitor XPENDING and per-consumer pending counts; BUSYGROUP noise often hides a real backlog problem you should watch instead.
  • Reclaim stuck messages from dead consumers with XAUTOCLAIM/XCLAIM rather than recreating the group.
  • Keep group/stream names in config so multiple workers agree and the create race is harmless.
  • Drop consumer logs into the free incident assistant, and see more Redis guides.

Quick Command Reference

# Confirm the group exists (BUSYGROUP is expected)
redis-cli XINFO GROUPS <stream>
redis-cli XINFO STREAM <stream>

# Idempotent create (catch BUSYGROUP in code)
redis-cli XGROUP CREATE <stream> <group> '$' MKSTREAM

# Reset position or remove a consumer instead of recreating
redis-cli XGROUP SETID <stream> <group> 0
redis-cli XGROUP DELCONSUMER <stream> <group> <consumer>

# Backlog / stuck message inspection
redis-cli XPENDING <stream> <group>
redis-cli XINFO CONSUMERS <stream> <group>
redis-cli XAUTOCLAIM <stream> <group> <consumer> 60000 0

Conclusion

BUSYGROUP Consumer Group name already exists is almost always benign: XGROUP CREATE ran against a group that already exists. The typical situations are:

  1. The group was created on a previous boot (the normal case).
  2. Multiple workers racing to create the same group at startup.
  3. Non-idempotent bootstrap code that treats the redundant create as fatal.
  4. Confusing “recreate” with “reset position” — use XGROUP SETID.

The fix is client-side idempotency: run XGROUP CREATE ... MKSTREAM and ignore BUSYGROUP. Then spend your monitoring attention on the thing that actually matters — pending/backlog counts via XPENDING and XINFO CONSUMERS.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.