CRITICAL: Unhandled Asyncio Tasks (Fire-and-Forget Pattern) #1

Closed
opened 2026-02-16 21:57:25 +02:00 by Koko210 · 1 comment
Owner

What the Problem Is

When you use asyncio.create_task() without tracking or error handling, any exception that occurs in that background task is silently swallowed. The task runs in the background, and if it crashes, Python doesn'''t log the error or notify you in any way.

Where It Occurs

  • bot/bot.py#L300 - Bipolar interjection check
  • bot/bot.py#L372 - Image handling interjection
  • bot/bot.py#L454 - Video handling interjection
  • bot/bot.py#L576 - GIF handling interjection
  • bot/bot.py#L669 - Embed handling interjection
  • bot/bot.py#L861-L862 - Delayed wakeup task
  • bot/utils/autonomous.py#L169-L172 - Autonomous action tasks
  • bot/utils/bipolar_mode.py#L1116 - Bipolar argument task

Why This Is a Problem

  1. Silent Failures: Background tasks can crash without anyone knowing
  2. Feature Loss: Features like bipolar interjections, autonomous actions, or voice processing simply stop working
  3. Debugging Nightmare: You can'''t fix problems you don'''t know exist
  4. Resource Leaks: Crashed tasks might leave resources (files, connections) open

What Can Go Wrong

Scenario 1: Bipolar Interjection Fails

  1. User sends a message that should trigger Evil Miku to interject
  2. check_for_interjection() starts as a background task
  3. Inside the task, a network call to Cheshire Cat times out
  4. The task crashes with asyncio.TimeoutError
  5. No error is logged - the interjection just silently doesn'''t happen
  6. User is confused why Evil Miku didn'''t respond

Scenario 2: Voice Session Auto-Leave Fails

  1. Voice session is active, user joins the channel
  2. Auto-leave timer is set as a background task
  3. Before timer fires, the voice connection gets interrupted
  4. When the timer tries to execute, it references a closed voice client
  5. Task crashes with RuntimeError: WebSocket connection is closed
  6. No error logged - bot appears to be "stuck" in voice
  7. Bot won'''t auto-leave in future sessions either

Proposed Fix

Create a create_tracked_task() helper function that wraps all background tasks with error handling:

def create_tracked_task(coro, task_name="background_task"):
    """Create a task that logs errors instead of swallowing them"""
    async def wrapped():
        try:
            await coro
        except Exception as e:
            logger.error(f"{task_name} failed: {e}", exc_info=True)
            # Optionally: send notification to owner
            if globals.OWNER_USER_ID:
                try:
                    owner = globals.client.get_user(globals.OWNER_USER_ID)
                    if owner:
                        await owner.send(f"⚠️ Background task error: {task_name}\n```{e}```")
                except:
                    pass
    return asyncio.create_task(wrapped())

Severity

CRITICAL - Feature failures are invisible and can persist indefinitely without detection.

Files Affected

11 files total including bot.py, autonomous.py, bipolar_mode.py, voice_receiver.py, voice_manager.py

## What the Problem Is When you use `asyncio.create_task()` without tracking or error handling, any exception that occurs in that background task is silently swallowed. The task runs in the background, and if it crashes, Python doesn'\''t log the error or notify you in any way. ## Where It Occurs - `bot/bot.py#L300` - Bipolar interjection check - `bot/bot.py#L372` - Image handling interjection - `bot/bot.py#L454` - Video handling interjection - `bot/bot.py#L576` - GIF handling interjection - `bot/bot.py#L669` - Embed handling interjection - `bot/bot.py#L861-L862` - Delayed wakeup task - `bot/utils/autonomous.py#L169-L172` - Autonomous action tasks - `bot/utils/bipolar_mode.py#L1116` - Bipolar argument task ## Why This Is a Problem 1. **Silent Failures**: Background tasks can crash without anyone knowing 2. **Feature Loss**: Features like bipolar interjections, autonomous actions, or voice processing simply stop working 3. **Debugging Nightmare**: You can'\''t fix problems you don'\''t know exist 4. **Resource Leaks**: Crashed tasks might leave resources (files, connections) open ## What Can Go Wrong ### Scenario 1: Bipolar Interjection Fails 1. User sends a message that should trigger Evil Miku to interject 2. `check_for_interjection()` starts as a background task 3. Inside the task, a network call to Cheshire Cat times out 4. The task crashes with `asyncio.TimeoutError` 5. **No error is logged** - the interjection just silently doesn'\''t happen 6. User is confused why Evil Miku didn'\''t respond ### Scenario 2: Voice Session Auto-Leave Fails 1. Voice session is active, user joins the channel 2. Auto-leave timer is set as a background task 3. Before timer fires, the voice connection gets interrupted 4. When the timer tries to execute, it references a closed voice client 5. Task crashes with `RuntimeError: WebSocket connection is closed` 6. **No error logged** - bot appears to be "stuck" in voice 7. Bot won'\''t auto-leave in future sessions either ## Proposed Fix Create a `create_tracked_task()` helper function that wraps all background tasks with error handling: ```python def create_tracked_task(coro, task_name="background_task"): """Create a task that logs errors instead of swallowing them""" async def wrapped(): try: await coro except Exception as e: logger.error(f"{task_name} failed: {e}", exc_info=True) # Optionally: send notification to owner if globals.OWNER_USER_ID: try: owner = globals.client.get_user(globals.OWNER_USER_ID) if owner: await owner.send(f"⚠️ Background task error: {task_name}\n```{e}```") except: pass return asyncio.create_task(wrapped()) ``` ## Severity **CRITICAL** - Feature failures are invisible and can persist indefinitely without detection. ## Files Affected 11 files total including bot.py, autonomous.py, bipolar_mode.py, voice_receiver.py, voice_manager.py
Koko210 reopened this issue 2026-02-16 22:17:02 +02:00
Author
Owner

Fixed in commit 7b7abcf. Added utils/task_tracker.py with a create_tracked_task() wrapper that logs errors with full tracebacks, handles cancellation, and keeps strong references to prevent GC. Replaced all 17 fire-and-forget asyncio.create_task() calls across 7 files (bot.py, autonomous.py, bipolar_mode.py, uno.py, voice_receiver.py, persona_dialogue.py). Already-tracked tasks in voice_audio.py and voice_manager.py were left unchanged.

Fixed in commit 7b7abcf. Added utils/task_tracker.py with a create_tracked_task() wrapper that logs errors with full tracebacks, handles cancellation, and keeps strong references to prevent GC. Replaced all 17 fire-and-forget asyncio.create_task() calls across 7 files (bot.py, autonomous.py, bipolar_mode.py, uno.py, voice_receiver.py, persona_dialogue.py). Already-tracked tasks in voice_audio.py and voice_manager.py were left unchanged.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Koko210/miku-discord#1