Repository: Qiskit/qiskit (python)

Issue:
specifying nonexistent synthesis plugin does not raise error
### Environment

- **Qiskit Terra version**: 0.45.1
- **Python version**: 3.10.12
- **Operating system**: Arch Linux


### What is happening?

`generate_preset_pass_manager` does not raise an error for a nonexistent synthesis plugin, even though it does for a nonexistent stage plugin.

### How can we reproduce the issue?

```python
from qiskit.providers.fake_provider import FakeBelem
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

backend = FakeBelem()
pass_manager = generate_preset_pass_manager(
    optimization_level=3, backend=backend, unitary_synthesis_method="a"
)
```

### What should happen?

This does not raise an error. Instead, an error is raised when the pass manager is run. This is inconsistent with the transpiler stage plugins. For example, this raises an error:
```python
from qiskit.providers.fake_provider import FakeBelem
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

backend = FakeBelem()
pass_manager = generate_preset_pass_manager(
    optimization_level=3, backend=backend, routing_method="a"
)
```
```
TranspilerError: 'Invalid plugin name a for stage routing'
```

### Any suggestions?

The error should be raised when the pass manager is created, not when it is run.

Pull request:
Raise error eagerly on bad unitary synthesis method
### Summary
`generate_preset_pass_manager` now raises an error the pass manager is created, not when it is run.

Fixes #11355 



Patch:
diff --git a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py
index 145cebd5c..f7f30fc28 100644
--- a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py
+++ b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py
@@ -331,6 +331,11 @@ class UnitarySynthesis(TransformationPass):
             target: The optional :class:`~.Target` for the target device the pass
                 is compiling for. If specified this will supersede the values
                 set for ``basis_gates``, ``coupling_map``, and ``backend_props``.
+
+        Raises:
+            TranspilerError: if ``method`` was specified but is not found in the
+                installed plugins list. The list of installed plugins can be queried with
+                :func:`~qiskit.transpiler.passes.synthesis.plugin.unitary_synthesis_plugin_names`
         """
         super().__init__()
         self._basis_gates = set(basis_gates or ())
@@ -358,6 +363,9 @@ class UnitarySynthesis(TransformationPass):
 
         self._synth_gates = set(self._synth_gates) - self._basis_gates
 
+        if self.method != "default" and self.method not in self.plugins.ext_plugins:
+            raise TranspilerError(f"Specified method '{self.method}' not found in plugin list")
+
     def run(self, dag: DAGCircuit) -> DAGCircuit:
         """Run the UnitarySynthesis pass on ``dag``.
 
@@ -366,15 +374,7 @@ class UnitarySynthesis(TransformationPass):
 
         Returns:
             Output dag with UnitaryGates synthesized to target basis.
-
-        Raises:
-            TranspilerError: if ``method`` was specified for the class and is not
-                found in the installed plugins list. The list of installed
-                plugins can be queried with
-                :func:`~qiskit.transpiler.passes.synthesis.plugin.unitary_synthesis_plugin_names`
         """
-        if self.method != "default" and self.method not in self.plugins.ext_plugins:
-            raise TranspilerError("Specified method: %s not found in plugin list" % self.method)
 
         # If there aren't any gates to synthesize in the circuit we can skip all the iteration
         # and just return.
diff --git a/releasenotes/notes/move-synthesis-plugin-error-61e3683bf5a0c225.yaml b/releasenotes/notes/move-synthesis-plugin-error-61e3683bf5a0c225.yaml
new file mode 100644
index 000000000..6ceb03b1b
--- /dev/null
+++ b/releasenotes/notes/move-synthesis-plugin-error-61e3683bf5a0c225.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+  - |
+    The :class:`.UnitarySynthesis` transpiler pass will now generate an error on initialization when
+    a nonexistent sythesis plugin is specified, rather than waiting until runtime to raise.  Fixed
+    `#11355 <https://github.com/Qiskit/qiskit/issues/11355>`__.


Test patch:
diff --git a/test/python/transpiler/test_stage_plugin.py b/test/python/transpiler/test_stage_plugin.py
index 1279fae46..d11fcb1c8 100644
--- a/test/python/transpiler/test_stage_plugin.py
+++ b/test/python/transpiler/test_stage_plugin.py
@@ -22,6 +22,7 @@ from qiskit.circuit.quantumcircuit import QuantumCircuit
 from qiskit.compiler.transpiler import transpile
 from qiskit.test import QiskitTestCase
 from qiskit.transpiler import PassManager, PassManagerConfig, CouplingMap
+from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
 from qiskit.transpiler.preset_passmanagers.builtin_plugins import BasicSwapPassManager
 from qiskit.transpiler.preset_passmanagers.plugin import (
     PassManagerStagePluginManager,
@@ -113,3 +114,16 @@ class TestBuiltinPlugins(QiskitTestCase):
         backend = QasmSimulatorPy()
         counts = backend.run(tqc, shots=1000).result().get_counts()
         self.assertDictAlmostEqual(counts, {"0000": 500, "1111": 500}, delta=100)
+
+    @combine(
+        optimization_level=list(range(4)),
+    )
+    def test_unitary_synthesis_plugins(self, optimization_level):
+        """Test unitary synthesis plugins"""
+        backend = QasmSimulatorPy()
+        with self.assertRaises(TranspilerError):
+            _ = generate_preset_pass_manager(
+                optimization_level=optimization_level,
+                backend=backend,
+                unitary_synthesis_method="not a method",
+            )