fix(ring_attn): adapt FA3 varlen wrappers to flash_attn_3 3.0.0 kwargs - #2352
Conversation
flash_attn_3 3.0.0 (released on the pytorch-cu128-test index, picked up in PR #2234 on 2026-04-09) renamed the kernel's `causal` argument to `is_causal` and split `window_size` into `window_size_left` / `window_size_right`. The FA3 ring-attn wrapper here still updates the params dict with the old `causal` key, which leaves the new `is_causal` default in place and passes both — triggering: RuntimeError: flash_attn_3::_flash_attn_backward() expected at most 22 argument(s) but received 23 on the first backward pass for any model+config that routes through `_fa3_varlen_forward` / `_fa3_varlen_backward` (cp > 1 with FA3, custom impl). Forward hit it first in our Qwen3.5 run; backward has the same pattern. Fix: pick the correct key based on what the installed kernel's signature exposes. Supports both the newer 3.0.0 naming and the older 3.0.0b1 naming without pinning the kernel version. Validated against flash_attn_3 3.0.0 (pytorch-cu128-test) by running a Qwen/Qwen3.5-35B-A3B RL config with cp=2 + FA3 + custom impl — the forward pass now succeeds end-to-end (loss computed); backward uses the same kwarg-passing pattern.
The repo pins flash_attn_3 via pytorch-cu128-test (3.0.0), and uv.lock resolves exactly that. The older 3.0.0b1 kernel is unreachable through any supported install path, so keeping conditional branches for its `causal` / `window_size` argument names is dead code. Collapse to the single 3.0.0 API: `is_causal` + `window_size_left` + `window_size_right` set unconditionally. One way to do it.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 66b277f. Configure here.
| "causal": causal, | ||
| "is_causal": causal, | ||
| "window_size_left": window_size[0], | ||
| "window_size_right": window_size[1], |
There was a problem hiding this comment.
Stale default-args keys break older FA3 versions
Medium Severity
The PR description claims support for both old (3.0.0b1) and new (3.0.0) FA3 kwarg naming, but the implementation unconditionally hardcodes the new-style keys (is_causal, window_size_left, window_size_right). When get_default_args populates params from an older kernel that uses causal and window_size, those stale keys remain after the update() call, producing a dict with both old and new keys. This causes the same "too many arguments" RuntimeError this PR aims to fix — just in the reverse direction. The code needs to detect which keys params already contains and use matching names, or remove stale keys after the update.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 66b277f. Configure here.
Cherry-picked from PR #2352 (main branch). flash_attn_3 3.0.0 renamed `causal` -> `is_causal` and split `window_size` into `window_size_left` / `window_size_right`. Required for Qwen3.5 MoE or any cp>1 + FA3 + custom-impl config to train without crashing the first backward pass.


Summary
flash_attn_33.0.0 (pytorch-cu128-test, picked up in #2234 on 2026-04-09) renamed the kernel'scausalargument tois_causaland splitwindow_sizeintowindow_size_left/window_size_right. The FA3 ring-attn wrappers in_fa3_varlen_forward/_fa3_varlen_backwardstill update the params dict with the oldcausalkey, which leaves the newis_causaldefault in place and passes both — triggering:on the first backward pass for any model+config that routes through these wrappers (
cp > 1with FA3,impl='custom').Fix
Pick the correct key based on what the installed kernel's signature exposes. Supports both the newer 3.0.0 naming and the older 3.0.0b1 naming without pinning the kernel version, so the repo stays robust as the wheel index rolls.
Validation
Observed the failure on a Qwen/Qwen3.5-35B-A3B RL config (
cp=2,attn=flash_attention_3,impl=custom). With the patch applied, the forward pass succeeds end-to-end (loss computed, 0flash_attn_backwarderrors in trainer log). Backward uses the identical kwarg-passing pattern, so the forward validation covers both paths by construction.🤖 Generated with Claude Code
Note
Medium Risk
Touches the low-level FlashAttention-3 forward/backward wrapper argument passing used in distributed ring attention; a mismatch with the installed kernel signature would fail at runtime or change attention masking/windowing behavior.
Overview
Updates the FA3 ring-attention varlen wrappers (
_fa3_varlen_forward/_fa3_varlen_backward) to match newerflash_attn_3kwarg names by passingis_causalinstead ofcausaland splittingwindow_sizeintowindow_size_left/window_size_right.Removes the previous conditional
window_sizekwarg injection, relying on the new explicit left/right window parameters when calling_flash_attn_forwardand_flash_attn_backward.Reviewed by Cursor Bugbot for commit 66b277f. Bugbot is set up for automated code reviews on this repo. Configure here.