Repository navigation
fix(paraformer): CIF crashes (IndexError) on segments with no fired boundaries - #3028
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces early-return checks in both cif_v1_export and cif_v1 to handle cases where no integration boundaries fire, preventing potential IndexError issues. However, the review highlights a critical bug where fire_idxs and fires are referenced before they are defined, which would lead to a NameError at runtime. A code suggestion is provided to safely evaluate the condition using alphas and correctly initialize fires before returning.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if fire_idxs.sum() == 0: | ||
| # No integration boundaries fired (e.g. a very short / silent | ||
| # segment): return zero frames instead of indexing into the | ||
| # resulting empty tensors, which raised an IndexError. | ||
| max_label_len = torch.round(alphas.sum(-1)).int().max() | ||
| return ( | ||
| torch.zeros(batch_size, max_label_len, hidden_size, dtype=dtype, device=device), | ||
| fires, | ||
| ) |
There was a problem hiding this comment.
In cif_v1_export, fire_idxs and fires are referenced before they are defined. This will raise a NameError (or fail TorchScript compilation) at runtime.
Since alphas are non-negative, the condition fire_idxs.sum() == 0 is mathematically equivalent to torch.floor(alphas.sum(-1)).sum() == 0. We can use this check to avoid any undefined variable issues and completely bypass the need to compute fire_idxs beforehand in the early-return case. In this case, fires is simply the cumulative sum of alphas cast to float32.
| if fire_idxs.sum() == 0: | |
| # No integration boundaries fired (e.g. a very short / silent | |
| # segment): return zero frames instead of indexing into the | |
| # resulting empty tensors, which raised an IndexError. | |
| max_label_len = torch.round(alphas.sum(-1)).int().max() | |
| return ( | |
| torch.zeros(batch_size, max_label_len, hidden_size, dtype=dtype, device=device), | |
| fires, | |
| ) | |
| if torch.floor(alphas.sum(-1)).sum() == 0: | |
| # No integration boundaries fired (e.g. a very short / silent | |
| # segment): return zero frames instead of indexing into the | |
| # resulting empty tensors, which raised an IndexError. | |
| max_label_len = torch.round(alphas.sum(-1)).int().max() | |
| fires = torch.cumsum(alphas, dim=1, dtype=torch.float64).to(torch.float32) | |
| return ( | |
| torch.zeros(batch_size, max_label_len, hidden_size, dtype=dtype, device=device), | |
| fires, | |
| ) |
… is defined The empty-fire guard added in #3028 was inserted before fire_idxs is computed in the @torch.jit.script cif_v1_export, so TorchScript failed to compile the module (undefined value fire_idxs) and any Paraformer export path that imports it broke. Move the guard to right after fire_idxs/fires are computed, matching cif_v1, and return zero frames + fires consistently. Verified: TorchScript compiles, empty-fire returns zeros without IndexError, and Paraformer inference is unchanged on normal audio.
cif_v1(andcif_v1_export) crash withIndexError: index is out of bounds for dimension with size 0when a segment produces no CIF firings (e.g. a very short or near-silent VAD segment):frames = prefix_sum_hidden[fire_idxs]is empty, soshift_frames[shift_batch_idxs] = 0indexes into an empty tensor.\n\nRepro: Paraformer-zh (funasr/paraformer-zh) on a 184-file Chinese benchmark crashed on 5 files. Added an early return of zero frames for the no-fire case.\n\nVerified: with the guard, all 184 files decode (was 179/184), and the micro-average CER is unchanged at 10.17% (matches the published benchmark).