Source code for qbraid.runtime.exceptions

# Copyright 2025 qBraid
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Module defining exceptions for errors raised while processing a device.

"""

from typing import Optional

from qbraid.exceptions import QbraidError


[docs] class ProgramValidationError(QbraidError): """Base class for errors raised while validating a quantum program."""
[docs] class QbraidRuntimeError(QbraidError): """Base class for errors raised while submitting a quantum job."""
[docs] class ResourceNotFoundError(QbraidError): """Exception raised when the desired resource could not be found."""
[docs] class RuntimeAPIError(QbraidRuntimeError, ValueError): """Exception raised when a provider's REST API returns an error response. Carries the HTTP status code so callers can branch on the failure mode (e.g. distinguish "job doesn't exist" from "credentials rejected") instead of string-matching the exception message. Where the provider returns a structured error body, ``error_code`` holds the provider's own error identifier (finer-grained than the HTTP status), ``trace`` the request id to quote in a support ticket, ``solution`` the provider's user-facing remediation text, and ``more_info`` a link to its error docs. All are None when the provider returned no structured error. ``solution`` is a suggestion from the provider, not gospel: it may be stale, may contain markup, and may reference the provider's own SDK rather than the caller's. Present it to users deliberately, not blindly. Note: this also subclasses ``ValueError`` because these provider paths previously raised a bare ``ValueError``. Keeping that base means existing ``except ValueError`` code keeps working. It is transitional and can be dropped in a future major release. """ # pylint: disable-next=too-many-arguments def __init__( self, message: str, status_code: Optional[int] = None, error_code: Optional[str] = None, trace: Optional[str] = None, solution: Optional[str] = None, more_info: Optional[str] = None, ): super().__init__(message) self.status_code = status_code self.error_code = error_code self.trace = trace self.solution = solution self.more_info = more_info
[docs] class AuthorizationError(RuntimeAPIError): """Exception raised when provider credentials are missing, expired, or rejected. Corresponds to a 401/403 from the provider — the request was well-formed but the caller is not authenticated/authorized. """
[docs] class JobNotFoundError(RuntimeAPIError, ResourceNotFoundError): """Exception raised when the requested job/task does not exist (404). Inherits from :class:`ResourceNotFoundError` so existing handlers that catch that keep working, and from :class:`RuntimeAPIError` so callers get ``status_code`` and can catch every provider API error uniformly. """
[docs] class JobStateError(QbraidError): """Class for errors raised due to the state of a quantum job"""
[docs] class DeviceProgramTypeMismatchError(ProgramValidationError): """ Exception raised when the program type does not match the Experiment type. """ def __init__(self, program, expected_type, experiment_type): message = ( f"Incompatible program type: '{type(program).__name__}'. " f"Experiment type '{experiment_type}' " f"requires a program of type '{expected_type}'." ) super().__init__(message)