You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Detector sampler raises IndexError when a non-Clifford block feeds no detector #260
Hi! While fuzzing the statevector backend before 1.0.0, we found a small circuit that compile_detector_sampler can't sample. The non-Clifford part on qubits 0–1 isn't read by any detector or observable:
importtsimc=tsim.Circuit("""U3(0.25, -0.25, 0.825) 0YCY 1 0U3(0.125, 0.595, 0.5) 0SQRT_YY 1 0MR 1X_ERROR(0.1) 2M 2DETECTOR rec[-1]""")
c.compile_sampler(seed=0).sample(3) # worksc.compile_detector_sampler(seed=0).sample(5) # IndexError: index -1 is out of bounds for axis 0 with size 0
Expected: 5 rows with one detector, which fires about 10% of the time.
What seems to happen:compile_program (src/tsim/compile/pipeline.py) still compiles the unread component, which then has rotations but no outputs and no symbols. lane_program (src/tsim/statevector/shared.py, lane_dormant = dormant & read[branch]) then indexes the empty read array with a branch of -1.
When the component does have symbols, read[-1] just reads an unrelated entry, and dormant masks it out. So the visible effect is the crash; we found no case of wrong samples.
Possible fixes: skip components without outputs when compiling for the detector sampler, or guard the index (e.g. read[np.maximum(branch, 0)] together with the existing dormant mask).
Random circuits hit this about once in 20k. It reproduces on main (e3a465b) and on #259 (a9af140).
A small correction and a few more triggers, from a 5-hour fuzzing run:
compile_sampler can crash too. It does when the circuit has no measurements at all. The fuzzer's smallest reproducer raises the same IndexError from both samplers for any seed:
Other shapes that hit the same line (detector sampler):
classical feedback (CY rec[-2] 2) onto a non-Clifford qubit that is never measured again;
SPP_DAG products on such qubits;
a heralded channel (HERALDED_ERASE, HERALDED_PAULI_CHANNEL_1, even at p=0) on a non-Clifford qubit that is never measured again. The fuzzer reported this one; I haven't reproduced it myself yet.
In every case the cause is read[branch] with branch == -1 in lane_program (src/tsim/statevector/shared.py:208). The fuzzer saw 18 crashes, 17 of them on this line. Across about 96k circuits checked against an exact oracle, it found no wrong samples.
Activity
Drop components without outputs before compiling
rafaelha commentedon Nov 4, 2026
A small correction and a few more triggers, from a 5-hour fuzzing run:
compile_samplercan crash too. It does when the circuit has no measurements at all. The fuzzer's smallest reproducer raises the sameIndexErrorfrom both samplers for any seed:CY rec[-2] 2) onto a non-Clifford qubit that is never measured again;SPP_DAGproducts on such qubits;HERALDED_ERASE,HERALDED_PAULI_CHANNEL_1, even at p=0) on a non-Clifford qubit that is never measured again. The fuzzer reported this one; I haven't reproduced it myself yet.In every case the cause is
read[branch]withbranch == -1inlane_program(src/tsim/statevector/shared.py:208). The fuzzer saw 18 crashes, 17 of them on this line. Across about 96k circuits checked against an exact oracle, it found no wrong samples.🤖 Generated with Claude Code
Drop components without outputs before compiling (QuEraComputing#262)