Qiskit / qiskit-ibm-runtime

IBM Client for Qiskit Runtime
https://docs.quantum.ibm.com/api/qiskit-ibm-runtime
Apache License 2.0
158 stars 156 forks source link

`Session.from_id` raises ValueError if backend not specified with ibm_quantum channel #1324

Closed mriedem closed 7 months ago

mriedem commented 10 months ago

Describe the bug

The backend kwarg to Session.from_id is deprecated:

https://github.com/Qiskit/qiskit-ibm-runtime/blob/stable/0.17/qiskit_ibm_runtime/session.py#L312

But if you don't specify a backend you get a ValueError:

.tox/staging/lib/python3.8/site-packages/qiskit_ibm_runtime/session.py:312: in from_id
    session = cls(service, backend)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <qiskit_ibm_runtime.session.Session object at 0x7f8765666fd0>, service = <QiskitRuntimeService>, backend = None, max_time = None

    def __init__(
        self,
        service: Optional[QiskitRuntimeService] = None,
        backend: Optional[Union[str, IBMBackend]] = None,
        max_time: Optional[Union[int, str]] = None,
    ):  # pylint: disable=line-too-long
        """Session constructor.

        Args:
            service: Optional instance of the ``QiskitRuntimeService`` class.
                If ``None``, the service associated with the backend, if known, is used.
                Otherwise ``QiskitRuntimeService()`` is used to initialize
                your default saved account.
            backend: Optional instance of :class:`qiskit_ibm_runtime.IBMBackend` class or
                string name of backend. An instance of :class:`qiskit_ibm_provider.IBMBackend` will not work.
                If not specified, a backend will be selected automatically (IBM Cloud channel only).

            max_time: (EXPERIMENTAL setting, can break between releases without warning)
                Maximum amount of time, a runtime session can be open before being
                forcibly closed. Can be specified as seconds (int) or a string like "2h 30m 40s".
                This value must be less than the
                `system imposed maximum
                <https://qiskit.org/documentation/partners/qiskit_ibm_runtime/faqs/max_execution_time.html>`_.

        Raises:
            ValueError: If an input value is invalid.
        """

        if service is None:
            if isinstance(backend, IBMBackend):
                self._service = backend.service
            else:
                self._service = (
                    QiskitRuntimeService()
                    if QiskitRuntimeService.global_service is None
                    else QiskitRuntimeService.global_service
                )

        else:
            self._service = service

        if self._service.channel == "ibm_quantum" and not backend:
>           raise ValueError('"backend" is required for ``ibm_quantum`` channel.')
E           ValueError: "backend" is required for ``ibm_quantum`` channel.

.tox/staging/lib/python3.8/site-packages/qiskit_ibm_runtime/session.py:111: ValueError

Steps to reproduce

This is a simple little test I wrote which I expect to raise an error but not the ValueError about a backend not being specified:

def test_using_arbitrary_session_id_should_fail(service):
    session_id = 'test_using_arbitrary_session_id_should_fail'
    session = Session.from_id(session_id, service)
    with pytest.raises(Exception) as ex:
        run_job(session=session)
    assert 'Check the session ID is correct.' in str(ex)

Expected behavior

The API should reject the request since the session doesn't exist with the given id.

Suggested solutions

n/a - it's confusing because the backend kwarg is deprecated so I was trying to stop using it, but when you stop using it with the ibm_quantum channel you get an error because it's actually required...

Additional Information

kt474 commented 9 months ago

In hindsight, we definitely should've waited for session.details() before releasing the from_id() method. While passing in the backend parameter works, having the option to pass in any backend is confusing. We can get the backend from session.details, but that requires the service parameter which we unfortunately have has optional.

Not sure the best way to handle this from a deprecation perspective, but in #1311, from_id() is updated to work as long as backend or service are passed in and an error is thrown if neither are passed. So in short, we want backend to be deprecated but service to be a required argument.

kt474 commented 7 months ago

Handled in https://github.com/Qiskit/qiskit-ibm-runtime/pull/1311