Environment
- Qiskit version: 2.4.1 (writer); 2.3.x (reader)
- Python version:
- Operating system:
I am opening this issue in collaboration with Claude 4.6, who originally found it, and did the technical writing below. I verified that the snippet fails as described.
What is happening?
A QPY file containing a PauliProductMeasurement gate written by Qiskit 2.4 cannot be loaded by Qiskit 2.3. The Rust writer in 2.4 serializes the three parameters of PauliProductMeasurement as two GenericValue::Tuple<Bool> (the z and x bit arrays) and one GenericValue::Bool (the neg flag). The Bool type uses type key b'b'.
The Python 2.3 _loads_instruction_parameter in circuits.py handles Container.TUPLE = b"t" directly (before reaching loads_value()), so the outer tuple level is read successfully. The failure occurs one level deeper: each inner Bool element has type key b'b', which falls through all explicit checks in _loads_instruction_parameter to the else branch, which calls value.loads_value(b'b', ...). That function tries type_keys.Value(b'b') and raises:
ValueError: b'b' is not a valid Value
because b'b' is not a member of the 2.3 Value enum. The 2.4→2.4 round-trip works because the Rust reader has ValueType::Bool = b'b'. The bug only manifests in the cross-version 2.4→2.3 direction.
How can we reproduce the issue?
# Step 1: in a Qiskit 2.4 environment — write the file
import io
from qiskit import QuantumCircuit
from qiskit.circuit.library import PauliProductMeasurement
from qiskit.quantum_info import Pauli
from qiskit import qpy
ppm = PauliProductMeasurement(Pauli("ZXY"))
qc = QuantumCircuit(ppm.num_qubits, ppm.num_clbits)
qc.append(ppm, range(ppm.num_qubits), range(ppm.num_clbits))
with open("/tmp/ppm.qpy", "wb") as f:
qpy.dump(qc, f)
print("Written /tmp/ppm.qpy")
# Step 2: in a Qiskit 2.3 environment — try to load the file
from qiskit import qpy
with open("/tmp/ppm.qpy", "rb") as f:
qpy.load(f) # raises ValueError: b'b' is not a valid Value
What should happen?
A QPY file written by Qiskit 2.4 containing standard library gates such as PauliProductMeasurement should be loadable by Qiskit 2.3. QPY version 17 should be forwards-compatible for gates that existed in 2.3.
Any suggestions?
Environment
I am opening this issue in collaboration with Claude 4.6, who originally found it, and did the technical writing below. I verified that the snippet fails as described.
What is happening?
A QPY file containing a
PauliProductMeasurementgate written by Qiskit 2.4 cannot be loaded by Qiskit 2.3. The Rust writer in 2.4 serializes the three parameters ofPauliProductMeasurementas twoGenericValue::Tuple<Bool>(thezandxbit arrays) and oneGenericValue::Bool(thenegflag). TheBooltype uses type keyb'b'.The Python 2.3
_loads_instruction_parameterincircuits.pyhandlesContainer.TUPLE = b"t"directly (before reachingloads_value()), so the outer tuple level is read successfully. The failure occurs one level deeper: each innerBoolelement has type keyb'b', which falls through all explicit checks in_loads_instruction_parameterto theelsebranch, which callsvalue.loads_value(b'b', ...). That function triestype_keys.Value(b'b')and raises:because
b'b'is not a member of the 2.3Valueenum. The 2.4→2.4 round-trip works because the Rust reader hasValueType::Bool = b'b'. The bug only manifests in the cross-version 2.4→2.3 direction.How can we reproduce the issue?
What should happen?
A QPY file written by Qiskit 2.4 containing standard library gates such as
PauliProductMeasurementshould be loadable by Qiskit 2.3. QPY version 17 should be forwards-compatible for gates that existed in 2.3.Any suggestions?