# TextGenerate 报错修复：cuDNN Frontend "No valid execution plans built"（2026-09-09）

## 现象
Krea2 工作流中 **TextGenerate 节点（Qwen3-VL 文本编码器）**生成 token 时报错：

```
RuntimeError: cuDNN Frontend error: [cudnn_frontend] Error: No valid execution plans built.
```

位置：`comfy/text_encoders/llama.py` → `optimized_attention` → `attention_pytorch` → `comfy/ops.py:95` → `F.scaled_dot_product_attention`。
环境：RTX 5060 Ti（Blackwell sm_120）、PyTorch 2.11.0+cu130、cuDNN v9、ComfyUI 0.34.0（--use-sage-attention 等 v6 参数）。

## 根因
- Qwen3-VL 文本编码器为 **GQA 注意力**（`enable_gqa=True`），带 attention_mask；
- `comfy/ops.py` 的 SDPA 调度优先级为 `FLASH → CUDNN → EFFICIENT → MATH`；
- 该形状下 flash/efficient 不可用 → 调度落入 **cuDNN attention**；
- cuDNN frontend 在 Blackwell 上为该形状**构建执行计划失败**，且**抛异常不回退到 MATH**（PyTorch/cuDNN 已知行为，非本机配置错误）。

## 修复（2026-09-09，GPU 机）
修改 `/home/zyw/ComfyUI/comfy/ops.py`：
1. 从 `SDPA_BACKEND_PRIORITY` 中移除 `CUDNN_ATTENTION`（保留 FLASH → EFFICIENT → MATH，MATH 兜底永远可构建计划）；
2. 追加 `torch.backends.cuda.enable_cudnn_sdp(False)`（双保险，防止小张量旁路路径仍选中 cuDNN）。

- 备份：`/home/zyw/ComfyUI/comfy/ops.py.bak-before-cudnnfix`
- 重启 ComfyUI（v6 脚本，新 PID），HTTP 200 验证通过。
- ⚠️ **若日后 ComfyUI git 更新覆盖 ops.py，需重新打此补丁**（文件内已留注释说明）。

## 影响面
仅禁用了 cuDNN SDPA 后端；flash/efficient/math 注意力不受影响（math 最慢但正确）。扩散去噪走 SageAttention，与本补丁无关。LLM 文本生成本身计算量小，性能影响可忽略。

## 验证
用户重跑原失败工作流（TextGenerate），确认不再报错即收尾。

---

## 2026-09-15 复盘：在实机上逐条复现，机制已完全确认

> 起因：升级 ComfyUI 后要重新打补丁，被追问「这个崩溃核实过吗」。原来的根因描述**方向正确但不完整**，
> 下面是实测复现（RTX 5060 Ti / cc 12.0 / torch 2.11.0+cu130 / cuDNN 9.19.0）。

### 复现实验（GQA 16q/4kv + float mask + bf16/fp16 均一致）

| 调用方式 | 结果 |
|---|---|
| 只允许 CUDNN | ❌ `RuntimeError: cuDNN Frontend error: [cudnn_frontend] Error: No valid execution plans built.` |
| 只允许 FLASH | ❌ `No available kernel`（GQA+mask 不支持） |
| 只允许 EFFICIENT | ❌ `No available kernel`（dense 输入要求 num_heads 相同） |
| 只允许 MATH | ✅ OK |
| `sdpa_kernel(PRI)` **不带** `set_priority` | ✅ OK（cuDNN 失败被容忍，落到 MATH） |
| **`sdpa_kernel(PRI, set_priority=True)` ← 上游 ComfyUI 的实际写法** | ❌ **复现原报错** |
| 去 CUDNN 后的列表 + `set_priority=True` | ✅ OK（**补丁有效**） |

### 完整因果链（三段缺一不可）

1. Qwen3-VL 文本编码走 **GQA + attention_mask**，形状上 flash 与 efficient **都没有可用内核**
   （实测 `can_use_flash=False`、`can_use_efficient=False`）；
2. 但 **`can_use_cudnn_attention(params)` 返回 `True`（谎报）** —— 因为该判定只看"后端是否被启用/参数是否合法"，
   并不知道 cuDNN frontend 在实际建图时会失败；
3. 上游 `comfy/ops.py` 的 **GQA 保护**正是用这三个 `can_use_*` 判断要不要**手工展开 KV 头**：
   因为 cuDNN 谎报 True，它认为"原生 GQA 可用"→ **跳过了手工展开**；
   随后在 `sdpa_kernel(SDPA_BACKEND_PRIORITY, set_priority=True)` 里选后端：
   FLASH 失败 → **CUDNN 直接抛异常（`set_priority=True` 之下不会静默落到 MATH）** → 报错。

### 两个修正/补充

- **`set_priority=True` 是关键**：不带它时 cuDNN 的失败会被容忍并落到 MATH，所以"随便一次 SDPA 测试"复现不出来——
  必须照上游写法带 `set_priority=True`。
- **没有免改代码的等价开关**：实测 `TORCH_CUDNN_SDPA_ENABLED=0` 在 torch 2.11 上**无效**
  （`torch.backends.cuda.cudnn_sdp_enabled()` 仍为 True），所以**只能改 `comfy/ops.py`**（或用启动脚本注入 monkeypatch）。
- 补丁的实际作用：把 cuDNN 从候选里拿掉，于是同一路径变成 FLASH 失败 → EFFICIENT 失败 → **MATH 兜底成功**。

### 结论

09-09 的补丁**必要且正确**；但注意它是**上游交互缺陷**（ComfyUI 的 GQA 保护被骗 + torch/cuDNN 在 sm_120 上建图失败），
不只是"本机配置问题"。**每次 `git pull` ComfyUI 之后都必须重新应用该补丁。**
