Warning
This document is for an in-development version of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.
Source code for galaxy.exceptions
"""This module defines Galaxy's custom exceptions.
A Galaxy exception is an exception that extends :class:`MessageException` which
defines an HTTP status code (represented by the `status_code` attribute) and a
default error message.
New exceptions should be defined by adding an entry to `error_codes.json` in this
directory to define a default error message and a Galaxy "error code". A concrete
Python class should be added in this file defining an HTTP status code (as
`status_code`) and error code (`error_code`) object loaded dynamically from
`error_codes.json`.
Reflecting Galaxy's origins as a web application, these exceptions tend to be a
bit web-oriented. However this module is a dependency of modules and tools that
have nothing to do with the web - keep this in mind when defining exception names
and messages.
"""
from typing import Optional
from .error_codes import (
error_codes_by_name,
ErrorCode,
)
[docs]class MessageException(Exception):
"""Most generic Galaxy exception - indicates merely that some exceptional condition happened."""
# status code to be set when used with API.
status_code: int = 400
# Error code information embedded into API json responses.
err_code: ErrorCode = error_codes_by_name["UNKNOWN"]
[docs] def __init__(self, err_msg: Optional[str] = None, type="info", **extra_error_info):
self.err_msg = err_msg or self.err_code.default_error_message
self.type = type
self.extra_error_info = extra_error_info
[docs] @staticmethod
def from_code(status_code, message):
exception_class = MessageException
if status_code == 404:
exception_class = ObjectNotFound
elif status_code / 100 == 5:
exception_class = InternalServerError
return exception_class(message)
def __str__(self):
return self.err_msg
# Please keep the exceptions ordered by status code
[docs]class AcceptedRetryLater(MessageException):
status_code = 202
err_code = error_codes_by_name["ACCEPTED_RETRY_LATER"]
retry_after: int
[docs] def __init__(self, msg: Optional[str] = None, retry_after=60):
super().__init__(msg)
self.retry_after = retry_after
[docs]class NoContentException(MessageException):
status_code = 204
err_code = error_codes_by_name["NO_CONTENT_GENERIC"]
[docs]class ActionInputError(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_REQUEST_INVALID_PARAMETER"]
[docs]class DuplicatedSlugException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_SLUG_DUPLICATE"]
[docs]class DuplicatedIdentifierException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_IDENTIFIER_DUPLICATE"]
[docs]class ObjectAttributeInvalidException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_OBJECT_ATTRIBUTE_INVALID"]
[docs]class ObjectAttributeMissingException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_OBJECT_ATTRIBUTE_MISSING"]
[docs]class MalformedId(MessageException):
status_code = 400
err_code = error_codes_by_name["MALFORMED_ID"]
[docs]class UserInvalidRunAsException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_INVALID_RUN_AS"]
[docs]class MalformedContents(MessageException):
status_code = 400
err_code = error_codes_by_name["MALFORMED_CONTENTS"]
[docs]class UnknownContentsType(MessageException):
status_code = 400
err_code = error_codes_by_name["UNKNOWN_CONTENTS_TYPE"]
[docs]class RequestParameterMissingException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_REQUEST_MISSING_PARAMETER"]
[docs]class ToolMetaParameterException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_TOOL_META_PARAMETER_PROBLEM"]
[docs]class ToolMissingException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_TOOL_MISSING_PROBLEM"]
[docs] def __init__(self, err_msg: Optional[str] = None, type="info", tool_id=None, **extra_error_info):
super().__init__(err_msg, type, **extra_error_info)
self.tool_id = tool_id
[docs]class RequestParameterInvalidException(MessageException):
status_code = 400
err_code = error_codes_by_name["USER_REQUEST_INVALID_PARAMETER"]
[docs]class ToolInputsNotReadyException(MessageException):
status_code = 400
error_code = error_codes_by_name["TOOL_INPUTS_NOT_READY"]
[docs]class ToolInputsNotOKException(MessageException):
[docs] def __init__(self, err_msg: Optional[str] = None, type="info", *, src: str, id: int, **extra_error_info):
super().__init__(err_msg, type, **extra_error_info)
self.src = src
self.id = id
status_code = 400
error_code = error_codes_by_name["TOOL_INPUTS_NOT_OK"]
[docs]class RealUserRequiredException(MessageException):
status_code = 400
error_code = error_codes_by_name["REAL_USER_REQUIRED"]
[docs]class AuthenticationFailed(MessageException):
status_code = 401
err_code = error_codes_by_name["USER_AUTHENTICATION_FAILED"]
[docs]class AuthenticationRequired(MessageException):
status_code = 403
# TODO: as 401 and send WWW-Authenticate: ???
err_code = error_codes_by_name["USER_NO_API_KEY"]
[docs]class ItemAccessibilityException(MessageException):
status_code = 403
err_code = error_codes_by_name["USER_CANNOT_ACCESS_ITEM"]
[docs]class ItemOwnershipException(MessageException):
status_code = 403
err_code = error_codes_by_name["USER_DOES_NOT_OWN_ITEM"]
[docs]class ItemImmutableException(MessageException):
status_code = 403
err_code = error_codes_by_name["ITEM_IS_IMMUTABLE"]
[docs]class ConfigDoesNotAllowException(MessageException):
status_code = 403
err_code = error_codes_by_name["CONFIG_DOES_NOT_ALLOW"]
[docs]class InsufficientPermissionsException(MessageException):
status_code = 403
err_code = error_codes_by_name["INSUFFICIENT_PERMISSIONS"]
[docs]class UserCannotRunAsException(MessageException):
status_code = 403
err_code = error_codes_by_name["USER_CANNOT_RUN_AS"]
[docs]class UserRequiredException(MessageException):
status_code = 403
err_code = error_codes_by_name["USER_REQUIRED"]
[docs]class AdminRequiredException(MessageException):
status_code = 403
err_code = error_codes_by_name["ADMIN_REQUIRED"]
[docs]class UserActivationRequiredException(MessageException):
status_code = 403
err_code = error_codes_by_name["USER_ACTIVATION_REQUIRED"]
[docs]class ItemAlreadyClaimedException(MessageException):
status_code = 403
err_code = error_codes_by_name["ITEM_IS_CLAIMED"]
[docs]class ObjectNotFound(MessageException):
"""Accessed object was not found"""
status_code = 404
err_code = error_codes_by_name["USER_OBJECT_NOT_FOUND"]
[docs]class Conflict(MessageException):
status_code = 409
err_code = error_codes_by_name["CONFLICT"]
[docs]class DeprecatedMethod(MessageException):
"""
Method (or a particular form/arg signature) has been removed and won't be available later
"""
status_code = 410
err_code = error_codes_by_name["DEPRECATED_API_CALL"]
[docs]class ConfigurationError(Exception):
status_code = 500
err_code = error_codes_by_name["CONFIG_ERROR"]
[docs]class InconsistentDatabase(MessageException):
status_code = 500
err_code = error_codes_by_name["INCONSISTENT_DATABASE"]
[docs]class InconsistentApplicationState(MessageException):
status_code = 500
err_code = error_codes_by_name["INCONSISTENT_APPLICATION_STATE"]
[docs]class InternalServerError(MessageException):
status_code = 500
err_code = error_codes_by_name["INTERNAL_SERVER_ERROR"]
[docs]class ToolExecutionError(MessageException):
status_code = 500
err_code = error_codes_by_name["TOOL_EXECUTION_ERROR"]
[docs] def __init__(self, err_msg, type="error", job=None):
super().__init__(err_msg, type)
self.job = job
[docs]class NotImplemented(MessageException):
status_code = 501
err_code = error_codes_by_name["NOT_IMPLEMENTED"]
[docs]class InvalidFileFormatError(MessageException):
status_code = 500
err_code = error_codes_by_name["INVALID_FILE_FORMAT"]
[docs]class ReferenceDataError(MessageException):
status_code = 500
err_code = error_codes_by_name["REFERENCE_DATA_ERROR"]
[docs]class ServerNotConfiguredForRequest(MessageException):
# A bit like ConfigDoesNotAllowException but it has nothing to do with the user of the
# request being "forbidden". It just isn't configured.
status_code = 501
err_code = error_codes_by_name["SERVER_NOT_CONFIGURED_FOR_REQUEST"]