Source code for cadrumo.adapters.outbound.storage.errors

"""Typed exception hierarchy for the storage provider abstraction.

Provider and remote-mirror failures raised by
:class:`adapters.outbound.storage.protocol.StorageProvider` implementations use
subclasses of :class:`OutboundStorageError` so the application layer's sync
coordinator can dispatch on the concrete failure mode without parsing upstream
error strings. Each public leaf binds to a stable
:class:`core.errors.error_codes.ErrorCode` through
:mod:`core.errors.registry` so the CLI taxonomy stays explicit.

:class:`StorageCorruptionError` is the deliberate exception: it derives from
:class:`core.errors.hierarchy.CoreError` because it represents structurally invalid
sidecar metadata, not a remote-provider transport, quota, permission, or mirror
failure.

The `Outbound` prefix disambiguates this hierarchy from the persistence
side :class:`adapters.persistence.storage.errors.StorageError`, which
covers at-rest persistence and has a different parent chain.

See Also:
    :class:`adapters.outbound.storage.protocol.StorageProvider`
        Provider Protocol whose implementations raise this hierarchy.
    :class:`adapters.outbound.storage.records.ProviderObjectMetadata`
        Boundary record paired with integrity and corruption checks.
"""

from __future__ import annotations

from collections.abc import Mapping

from ....application.operator_actions.models import PreconditionVerdict
from ....core.errors.hierarchy import CadrumoError, CoreError, TerminalPreconditionErrorMixin


[docs] class OutboundStorageError(TerminalPreconditionErrorMixin[PreconditionVerdict], CadrumoError): """Base class for every outbound storage-provider failure."""
[docs] class OutboundStorageValidationError(OutboundStorageError): """Raised when storage operation parameters fail validation. Pydantic-facing callers translate this registered error at their narrow validator boundary when required; provider code keeps the registered outbound-storage type. """ def __init__( self, message: str | None = None, *, context: Mapping[str, object] | None = None, translated_message: str | None = None, precondition_verdict: PreconditionVerdict | None = None, ) -> None: """Initialize this public contract.""" super().__init__( message, context=context, translated_message=translated_message, precondition_verdict=precondition_verdict, )
[docs] class OutboundStorageNotFoundError(OutboundStorageError): """Raised when a requested object or namespace does not exist."""
[docs] class OutboundStorageConflictError(OutboundStorageError): """Raised when a put / move / rename collides with an existing object."""
[docs] class OutboundStoragePermissionError(OutboundStorageError): """Raised when the active credentials lack the required scope or grant."""
[docs] class OutboundStoragePathTooLongError(OutboundStorageError): """Raised when a resolved on-disk path exceeds the platform's path-length ceiling. Classified via :func:`core.paths.is_windows_long_path_error` from a caught ``WinError 3`` / ``WinError 206`` on legacy (non long-path-aware) Windows workstations. Distinct from :class:`OutboundStorageConflictError` so the CLI surfaces the actual cause (a storage root too deep for the ``MAX_PATH`` ceiling) instead of a generic write-conflict message. """
[docs] class OutboundStorageQuotaError(OutboundStorageError): """Raised when the backend rejects an operation due to quota exhaustion."""
[docs] class OutboundStorageNetworkError(OutboundStorageError): """Raised when the backend endpoint is unreachable (DNS/TLS/timeout)."""
[docs] class OutboundStorageIntegrityError(OutboundStorageError): """Raised when fetched provider data fails integrity checks. The shared hash comparison path is :func:`adapters.outbound.storage._integrity.verify_content_hash`. """
[docs] class OutboundStorageUnavailableError(OutboundStorageError): """Raised when the backend is reachable but signals temporary unavailability."""
[docs] class StorageCorruptionError(TerminalPreconditionErrorMixin[PreconditionVerdict], CoreError): """Raised when a sidecar file contains structurally invalid field types. As a :class:`core.errors.hierarchy.CoreError`, this indicates on-disk data corruption: the sidecar JSON parses successfully but a required field (e.g. ``byte_length``) carries a type that the runtime cannot coerce to the expected primitive. Unlike :class:`OutboundStorageIntegrityError`, which covers payload-byte hash mismatches from :func:`adapters.outbound.storage._integrity.verify_content_hash`, this error surfaces schema-level violations in the sidecar metadata file itself. """ def __init__( self, message: str | None = None, *, context: Mapping[str, object] | None = None, translated_message: str | None = None, precondition_verdict: PreconditionVerdict | None = None, ) -> None: """Initialize this public contract.""" super().__init__( message, context=context, translated_message=translated_message, precondition_verdict=precondition_verdict, )
__all__ = [ "OutboundStorageConflictError", "OutboundStorageError", "OutboundStorageIntegrityError", "OutboundStorageNetworkError", "OutboundStorageNotFoundError", "OutboundStoragePathTooLongError", "OutboundStoragePermissionError", "OutboundStorageQuotaError", "OutboundStorageUnavailableError", "OutboundStorageValidationError", "StorageCorruptionError", ]