# Task exception was never retrieved
future: <Task finished name='Task-5' coro=<worker() done, defined at app.py:42> exception=ValueError('bad payload')>

- **ID:** `python/task-exception-never-retrieved`
- **领域:** python
- **类别:** runtime_error
- **验证级别:** ai_generated
- **修复率:** 80%

## 根因

通过 asyncio.create_task() 创建的任务抛出异常，但没有人 await 该任务或附加完成回调，因此异常被丢弃。

## 版本兼容性

| 版本 | 状态 | 引入 | 弃用 |
|------|------|------|------|
| 3.8 | active | — | — |
| 3.9 | active | — | — |
| 3.10 | active | — | — |
| 3.11 | active | — | — |
| 3.12 | active | — | — |

## 解决方案

1. **** (90% 成功率)
   ```
   Attach a done callback that logs exceptions:

def _log(task):
    if (exc := task.exception()):
        logger.exception('task failed', exc_info=exc)

task = asyncio.create_task(worker())
task.add_done_callback(_log)
   ```
2. **** (95% 成功率)
   ```
   Keep strong references and await tasks in a TaskGroup (3.11+):

async with asyncio.TaskGroup() as tg:
    tg.create_task(worker())
   ```
3. **** (85% 成功率)
   ```
   For fire-and-forget, store tasks in a module-level set and remove in the callback to prevent GC.
   ```

## 无效尝试

- **** — Only adds more logging; the underlying exception is still lost. (70% 失败率)
- **** — Hides real bugs and still leaves the task result unretrieved. (80% 失败率)
- **** — Does not attach a handler to the task's exception. (85% 失败率)
