Repository: Qiskit/qiskit

Issue:
DAGCircuitError: 'bit mapping invalid
### Informations

- **Qiskit: 0.39.2**:
- **Python: 3.10.9**:
- **Mac**:

### What is the current behavior?
I'm implementing quantum half adder on Jupyter Notebook.
When I try running my circuit on the simulator "qasm_simulator", Jupyter said 

DAGCircuitError: 'bit mapping invalid: expected 4, got 8'

here is the code I've written. The error occurs on the last line of the third code.

```
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, execute, Aer
#SUM
X = QuantumRegister(1, "in |X⟩")
Y = QuantumRegister(1, "in |Y⟩")
sum_out = QuantumRegister(1, "out SUM |0⟩")
SUM = QuantumCircuit(X, Y, sum_out, name='SUM')
SUM.cx(1, 2)
SUM.cx(0, 2)

fig = SUM.draw('mpl', True)
SUM = SUM.to_instruction()
fig
```

```
#half_adder
cout = QuantumRegister(1, 'out Carry |0⟩')
c = ClassicalRegister(4)
hadder = QuantumCircuit(X,Y,sum_out,cout,c)
hadder.ccx(X,Y,cout)
hadder.append(SUM,[0,1,2])

show = hadder.draw("mpl",True)
hadder = hadder.to_instruction()
show
```

```
#testing half_adder
qu = QuantumRegister(4)
cl = ClassicalRegister(4)
circ = QuantumCircuit(qu,cl)
circ.x(qu[0])
circ.x(qu[1])
circ.append(hadder,[0,1,2,3])
    
for i in range(0,4):
    circ.measure(qu[i],cl[i])
circ.draw("mpl",True)
print(execute(circ,Aer.get_backend('qasm_simulator'), shots = 1).result().get_counts())
```



### What is the expected behavior?

I don't totally understand the error. I hope to troubleshoot to see the result.

### Suggested solutions



Discussion:
Your immediate problem is that the line
```python
circ.append(hadder, [0, 1, 2, 3])
```
doesn't include any classical arguments to apply `hadder` to, but it expects 4 (though they're not used).  Perhaps you either meant not to have the `ClassicalRegister` `c` in `hadder`, or you meant to write the above line as
```python
circ.append(hadder, [0, 1, 2, 3], [0, 1, 2, 3])
```

On our side, the `append` call I pulled out should have raised an error.  I'm not certain why it didn't, but it definitely looks like a bug that it didn't.

Resolving patch:
diff --git a/qiskit/circuit/instruction.py b/qiskit/circuit/instruction.py
--- a/qiskit/circuit/instruction.py
+++ b/qiskit/circuit/instruction.py
@@ -481,6 +481,11 @@ def broadcast_arguments(self, qargs, cargs):
                 f"The amount of qubit arguments {len(qargs)} does not match"
                 f" the instruction expectation ({self.num_qubits})."
             )
+        if len(cargs) != self.num_clbits:
+            raise CircuitError(
+                f"The amount of clbit arguments {len(cargs)} does not match"
+                f" the instruction expectation ({self.num_clbits})."
+            )
 
         #  [[q[0], q[1]], [c[0], c[1]]] -> [q[0], c[0]], [q[1], c[1]]
         flat_qargs = [qarg for sublist in qargs for qarg in sublist]


Test patch:
diff --git a/test/python/circuit/test_circuit_operations.py b/test/python/circuit/test_circuit_operations.py
--- a/test/python/circuit/test_circuit_operations.py
+++ b/test/python/circuit/test_circuit_operations.py
@@ -147,6 +147,16 @@ def test_append_rejects_wrong_types(self, specifier):
         with self.subTest("c list"), self.assertRaisesRegex(CircuitError, "Invalid bit index"):
             test.append(opaque, [[0]], [[specifier]])
 
+    @data([], [0], [0, 1, 2])
+    def test_append_rejects_bad_arguments_opaque(self, bad_arg):
+        """Test that a suitable exception is raised when there is an argument mismatch."""
+        inst = QuantumCircuit(2, 2).to_instruction()
+        qc = QuantumCircuit(3, 3)
+        with self.assertRaisesRegex(CircuitError, "The amount of qubit arguments"):
+            qc.append(inst, bad_arg, [0, 1])
+        with self.assertRaisesRegex(CircuitError, "The amount of clbit arguments"):
+            qc.append(inst, [0, 1], bad_arg)
+
     def test_anding_self(self):
         """Test that qc &= qc finishes, which can be prone to infinite while-loops.
 
@@ -1123,9 +1133,9 @@ def test_from_instructions(self):
         a, b, c, d = qreg
         x, y, z = creg
 
-        circuit_1 = QuantumCircuit(2)
+        circuit_1 = QuantumCircuit(2, 1)
         circuit_1.x(0)
-        circuit_2 = QuantumCircuit(2)
+        circuit_2 = QuantumCircuit(2, 1)
         circuit_2.y(0)
 
         def instructions():
diff --git a/test/python/circuit/test_control_flow_builders.py b/test/python/circuit/test_control_flow_builders.py
--- a/test/python/circuit/test_control_flow_builders.py
+++ b/test/python/circuit/test_control_flow_builders.py
@@ -91,7 +91,7 @@ def test_if_register(self):
 
         expected = QuantumCircuit(qr, cr)
         expected.measure(qr, cr)
-        expected.if_test((cr, 0), if_true0, [qr[0]], [cr[:]])
+        expected.if_test((cr, 0), if_true0, [qr[0]], cr)
 
         self.assertEqual(canonicalize_control_flow(test), canonicalize_control_flow(expected))
 
diff --git a/test/python/transpiler/test_check_map.py b/test/python/transpiler/test_check_map.py
--- a/test/python/transpiler/test_check_map.py
+++ b/test/python/transpiler/test_check_map.py
@@ -92,7 +92,7 @@ def test_swap_mapped_cf_true(self):
         qr = QuantumRegister(3)
         cr = ClassicalRegister(3)
         circuit = QuantumCircuit(qr, cr)
-        true_body = QuantumCircuit(qr)
+        true_body = QuantumCircuit(qr, cr)
         true_body.swap(0, 1)
         true_body.cx(2, 1)
         circuit.if_else((cr[0], 0), true_body, None, qr, cr)
@@ -110,7 +110,7 @@ def test_swap_mapped_cf_false(self):
         circuit = QuantumCircuit(qr, cr)
         true_body = QuantumCircuit(qr)
         true_body.cx(0, 2)
-        circuit.if_else((cr[0], 0), true_body, None, qr, cr)
+        circuit.if_else((cr[0], 0), true_body, None, qr, [])
         dag = circuit_to_dag(circuit)
         pass_ = CheckMap(coupling)
         pass_.run(dag)
@@ -123,7 +123,7 @@ def test_swap_mapped_cf_layout_change_false(self):
         qr = QuantumRegister(3)
         cr = ClassicalRegister(3)
         circuit = QuantumCircuit(qr, cr)
-        true_body = QuantumCircuit(qr)
+        true_body = QuantumCircuit(qr, cr)
         true_body.cx(1, 2)
         circuit.if_else((cr[0], 0), true_body, None, qr[[1, 0, 2]], cr)
         dag = circuit_to_dag(circuit)
@@ -140,7 +140,7 @@ def test_swap_mapped_cf_layout_change_true(self):
         circuit = QuantumCircuit(qr, cr)
         true_body = QuantumCircuit(qr)
         true_body.cx(0, 2)
-        circuit.if_else((cr[0], 0), true_body, None, qr[[1, 0, 2]], cr)
+        circuit.if_else((cr[0], 0), true_body, None, qr[[1, 0, 2]], [])
         dag = circuit_to_dag(circuit)
         pass_ = CheckMap(coupling)
         pass_.run(dag)
@@ -153,9 +153,9 @@ def test_swap_mapped_cf_different_bits(self):
         qr = QuantumRegister(3)
         cr = ClassicalRegister(3)
         circuit = QuantumCircuit(qr, cr)
-        true_body = QuantumCircuit(3)
+        true_body = QuantumCircuit(3, 1)
         true_body.cx(0, 2)
-        circuit.if_else((cr[0], 0), true_body, None, qr[[1, 0, 2]], cr)
+        circuit.if_else((cr[0], 0), true_body, None, qr[[1, 0, 2]], [cr[0]])
         dag = circuit_to_dag(circuit)
         pass_ = CheckMap(coupling)
         pass_.run(dag)
@@ -169,9 +169,9 @@ def test_disjoint_controlflow_bits(self):
         qr2 = QuantumRegister(3, "qrif")
         cr = ClassicalRegister(3)
         circuit = QuantumCircuit(qr1, cr)
-        true_body = QuantumCircuit(qr2)
+        true_body = QuantumCircuit(qr2, [cr[0]])
         true_body.cx(0, 2)
-        circuit.if_else((cr[0], 0), true_body, None, qr1[[1, 0, 2]], cr)
+        circuit.if_else((cr[0], 0), true_body, None, qr1[[1, 0, 2]], [cr[0]])
         dag = circuit_to_dag(circuit)
         pass_ = CheckMap(coupling)
         pass_.run(dag)
@@ -189,7 +189,7 @@ def test_nested_controlflow_true(self):
         true_body = QuantumCircuit(qr2, cr2)
         for_body = QuantumCircuit(3)
         for_body.cx(0, 2)
-        true_body.for_loop(range(5), body=for_body, qubits=qr2, clbits=cr2)
+        true_body.for_loop(range(5), body=for_body, qubits=qr2, clbits=[])
         circuit.if_else((cr1[0], 0), true_body, None, qr1[[1, 0, 2]], cr1)
         dag = circuit_to_dag(circuit)
         pass_ = CheckMap(coupling)
@@ -208,7 +208,7 @@ def test_nested_controlflow_false(self):
         true_body = QuantumCircuit(qr2, cr2)
         for_body = QuantumCircuit(3)
         for_body.cx(0, 2)
-        true_body.for_loop(range(5), body=for_body, qubits=qr2, clbits=cr2)
+        true_body.for_loop(range(5), body=for_body, qubits=qr2, clbits=[])
         circuit.if_else((cr1[0], 0), true_body, None, qr1[[0, 1, 2]], cr1)
         dag = circuit_to_dag(circuit)
         pass_ = CheckMap(coupling)
diff --git a/test/python/transpiler/test_clifford_passes.py b/test/python/transpiler/test_clifford_passes.py
--- a/test/python/transpiler/test_clifford_passes.py
+++ b/test/python/transpiler/test_clifford_passes.py
@@ -244,18 +244,12 @@ def test_if_else(self):
 
         test = QuantumCircuit(cliff1.num_qubits, 1)
         test.measure(0, 0)
-        test.if_else(
-            (test.clbits[0], True), inner_test.copy(), inner_test.copy(), test.qubits, test.clbits
-        )
+        test.if_else((test.clbits[0], True), inner_test.copy(), inner_test.copy(), test.qubits, [])
 
         expected = QuantumCircuit(combined.num_qubits, 1)
         expected.measure(0, 0)
         expected.if_else(
-            (expected.clbits[0], True),
-            inner_expected,
-            inner_expected,
-            expected.qubits,
-            expected.clbits,
+            (expected.clbits[0], True), inner_expected, inner_expected, expected.qubits, []
         )
 
         self.assertEqual(OptimizeCliffords()(test), expected)
diff --git a/test/python/transpiler/test_linear_functions_passes.py b/test/python/transpiler/test_linear_functions_passes.py
--- a/test/python/transpiler/test_linear_functions_passes.py
+++ b/test/python/transpiler/test_linear_functions_passes.py
@@ -417,7 +417,7 @@ def test_if_else(self, do_commutative_analysis):
         """Test that collection recurses into a simple if-else."""
         pass_ = CollectLinearFunctions(do_commutative_analysis=do_commutative_analysis)
 
-        circuit = QuantumCircuit(4)
+        circuit = QuantumCircuit(4, 1)
         circuit.cx(0, 1)
         circuit.cx(1, 0)
         circuit.cx(2, 3)
diff --git a/test/python/transpiler/test_optimize_1q_decomposition.py b/test/python/transpiler/test_optimize_1q_decomposition.py
--- a/test/python/transpiler/test_optimize_1q_decomposition.py
+++ b/test/python/transpiler/test_optimize_1q_decomposition.py
@@ -684,7 +684,7 @@ def test_if_else(self):
         test = QuantumCircuit(qr, cr)
         test.h(0)
         test.measure(0, 0)
-        test_true = QuantumCircuit(qr)
+        test_true = QuantumCircuit(qr, cr)
         test_true.h(qr[0])
         test_true.h(qr[0])
         test_true.h(qr[0])
@@ -693,7 +693,7 @@ def test_if_else(self):
         expected = QuantumCircuit(qr, cr)
         expected.u(np.pi / 2, 0, -np.pi, 0)
         expected.measure(0, 0)
-        expected_true = QuantumCircuit(qr)
+        expected_true = QuantumCircuit(qr, cr)
         expected_true.u(np.pi / 2, 0, -np.pi, qr[0])
         expected.if_else((0, True), expected_true, None, range(num_qubits), [0])
 
diff --git a/test/python/transpiler/test_optimize_swap_before_measure.py b/test/python/transpiler/test_optimize_swap_before_measure.py
--- a/test/python/transpiler/test_optimize_swap_before_measure.py
+++ b/test/python/transpiler/test_optimize_swap_before_measure.py
@@ -199,10 +199,12 @@ def test_nested_control_flow(self):
         base_expected.measure(1, 0)
 
         body_test = QuantumCircuit(2, 1)
-        body_test.for_loop((0,), None, base_expected.copy(), body_test.qubits, [])
+        body_test.for_loop((0,), None, base_expected.copy(), body_test.qubits, body_test.clbits)
 
         body_expected = QuantumCircuit(2, 1)
-        body_expected.for_loop((0,), None, base_expected.copy(), body_expected.qubits, [])
+        body_expected.for_loop(
+            (0,), None, base_expected.copy(), body_expected.qubits, body_expected.clbits
+        )
 
         test = QuantumCircuit(2, 1)
         test.while_loop((test.clbits[0], True), body_test, test.qubits, test.clbits)
diff --git a/test/python/transpiler/test_remove_barriers.py b/test/python/transpiler/test_remove_barriers.py
--- a/test/python/transpiler/test_remove_barriers.py
+++ b/test/python/transpiler/test_remove_barriers.py
@@ -91,10 +91,12 @@ def test_nested_control_flow(self):
         base_expected.measure(0, 0)
 
         body_test = QuantumCircuit(1, 1)
-        body_test.for_loop((0,), None, base_expected.copy(), body_test.qubits, [])
+        body_test.for_loop((0,), None, base_expected.copy(), body_test.qubits, body_test.clbits)
 
         body_expected = QuantumCircuit(1, 1)
-        body_expected.for_loop((0,), None, base_expected.copy(), body_expected.qubits, [])
+        body_expected.for_loop(
+            (0,), None, base_expected.copy(), body_expected.qubits, body_expected.clbits
+        )
 
         test = QuantumCircuit(1, 1)
         test.while_loop((test.clbits[0], True), body_test, test.qubits, test.clbits)
diff --git a/test/python/transpiler/test_remove_diagonal_gates_before_measure.py b/test/python/transpiler/test_remove_diagonal_gates_before_measure.py
--- a/test/python/transpiler/test_remove_diagonal_gates_before_measure.py
+++ b/test/python/transpiler/test_remove_diagonal_gates_before_measure.py
@@ -251,10 +251,12 @@ def test_nested_control_flow(self):
         base_expected.measure(1, 0)
 
         body_test = QuantumCircuit(2, 1)
-        body_test.for_loop((0,), None, base_expected.copy(), body_test.qubits, [])
+        body_test.for_loop((0,), None, base_expected.copy(), body_test.qubits, body_test.clbits)
 
         body_expected = QuantumCircuit(2, 1)
-        body_expected.for_loop((0,), None, base_expected.copy(), body_expected.qubits, [])
+        body_expected.for_loop(
+            (0,), None, base_expected.copy(), body_expected.qubits, body_expected.clbits
+        )
 
         test = QuantumCircuit(2, 1)
         test.while_loop((test.clbits[0], True), body_test, test.qubits, test.clbits)
diff --git a/test/python/transpiler/test_reset_after_measure_simplification.py b/test/python/transpiler/test_reset_after_measure_simplification.py
--- a/test/python/transpiler/test_reset_after_measure_simplification.py
+++ b/test/python/transpiler/test_reset_after_measure_simplification.py
@@ -180,10 +180,12 @@ def test_nested_control_flow(self):
         base_expected.x(0).c_if(0, True)
 
         body_test = QuantumCircuit(1, 1)
-        body_test.for_loop((0,), None, base_expected.copy(), body_test.qubits, [])
+        body_test.for_loop((0,), None, base_expected.copy(), body_test.qubits, body_test.clbits)
 
         body_expected = QuantumCircuit(1, 1)
-        body_expected.for_loop((0,), None, base_expected.copy(), body_expected.qubits, [])
+        body_expected.for_loop(
+            (0,), None, base_expected.copy(), body_expected.qubits, body_expected.clbits
+        )
 
         test = QuantumCircuit(1, 1)
         test.while_loop((test.clbits[0], True), body_test, test.qubits, test.clbits)
diff --git a/test/python/transpiler/test_unitary_synthesis.py b/test/python/transpiler/test_unitary_synthesis.py
--- a/test/python/transpiler/test_unitary_synthesis.py
+++ b/test/python/transpiler/test_unitary_synthesis.py
@@ -775,7 +775,7 @@ def test_if_simple(self):
         qc_true_body.unitary(qc_uni_mat, [0, 1])
 
         qc = QuantumCircuit(qr, cr)
-        qc.if_test((cr, 1), qc_true_body, [0, 1], [0, 1])
+        qc.if_test((cr, 1), qc_true_body, [0, 1], [])
         dag = circuit_to_dag(qc)
         cdag = UnitarySynthesis(basis_gates=basis_gates).run(dag)
         cqc = dag_to_circuit(cdag)
diff --git a/test/python/transpiler/test_unroll_custom_definitions.py b/test/python/transpiler/test_unroll_custom_definitions.py
--- a/test/python/transpiler/test_unroll_custom_definitions.py
+++ b/test/python/transpiler/test_unroll_custom_definitions.py
@@ -194,16 +194,16 @@ def test_nested_control_flow(self):
         while_body.append(TestCompositeGate(), [0], [])
 
         true_body = QuantumCircuit([qubit, clbit])
-        true_body.while_loop((clbit, True), while_body, [0], [0])
+        true_body.while_loop((clbit, True), while_body, [0], [])
 
         test = QuantumCircuit([qubit, clbit])
-        test.for_loop(range(2), None, for_body, [0], [0])
+        test.for_loop(range(2), None, for_body, [0], [])
         test.if_else((clbit, True), true_body, None, [0], [0])
 
         expected_if_body = QuantumCircuit([qubit, clbit])
-        expected_if_body.while_loop((clbit, True), pass_(while_body), [0], [0])
+        expected_if_body.while_loop((clbit, True), pass_(while_body), [0], [])
         expected = QuantumCircuit([qubit, clbit])
-        expected.for_loop(range(2), None, pass_(for_body), [0], [0])
+        expected.for_loop(range(2), None, pass_(for_body), [0], [])
         expected.if_else(range(2), pass_(expected_if_body), None, [0], [0])
 
         self.assertEqual(pass_(test), expected)