Skip to content

exceptions

lacuna.core.exceptions

Base exception hierarchy for the lacuna toolkit.

All custom exceptions inherit from LacunaError to enable precise error handling while maintaining compatibility with standard Python exceptions.

AnalysisError

Bases: LacunaError, RuntimeError

Raised when analysis computation fails.

Source code in src/lacuna/core/exceptions.py
class AnalysisError(LacunaError, RuntimeError):
    """Raised when analysis computation fails."""

    pass

AtlasNotFoundError

Bases: LacunaError, FileNotFoundError

Raised when atlas cannot be found or resolved.

Source code in src/lacuna/core/exceptions.py
class AtlasNotFoundError(LacunaError, FileNotFoundError):
    """Raised when atlas cannot be found or resolved."""

    pass

AuthenticationError

Bases: FetchError

Raised when authentication fails (missing or invalid API key).

Source code in src/lacuna/core/exceptions.py
class AuthenticationError(FetchError):
    """Raised when authentication fails (missing or invalid API key)."""

    def __init__(self, source: str, reason: str | None = None):
        self.source = source
        self.reason = reason
        message = f"Authentication failed for '{source}'"
        if reason:
            message += f": {reason}"
        super().__init__(message)

BIDSValidationError

Bases: LacunaError, ValueError

Raised when BIDS dataset structure is invalid.

Source code in src/lacuna/core/exceptions.py
class BIDSValidationError(LacunaError, ValueError):
    """Raised when BIDS dataset structure is invalid."""

    pass

ChecksumError

Bases: FetchError

Raised when file checksum verification fails.

Source code in src/lacuna/core/exceptions.py
class ChecksumError(FetchError):
    """Raised when file checksum verification fails."""

    def __init__(self, filepath: str, expected: str, actual: str):
        self.filepath = filepath
        self.expected = expected
        self.actual = actual
        message = (
            f"Checksum mismatch for '{filepath}': expected {expected[:16]}..., got {actual[:16]}..."
        )
        super().__init__(message)

ConnectomeNotFoundError

Bases: LacunaError, FileNotFoundError

Raised when connectome cannot be found or resolved.

Source code in src/lacuna/core/exceptions.py
class ConnectomeNotFoundError(LacunaError, FileNotFoundError):
    """Raised when connectome cannot be found or resolved."""

    pass

CoordinateSpaceError

Bases: LacunaError, ValueError

Raised when operations require specific coordinate space.

Source code in src/lacuna/core/exceptions.py
class CoordinateSpaceError(LacunaError, ValueError):
    """Raised when operations require specific coordinate space."""

    pass

DownloadError

Bases: FetchError

Raised when download fails after retries.

Source code in src/lacuna/core/exceptions.py
class DownloadError(FetchError):
    """Raised when download fails after retries."""

    def __init__(self, url: str, reason: str, retries: int = 0):
        self.url = url
        self.reason = reason
        self.retries = retries
        message = f"Download failed for '{url}': {reason}"
        if retries > 0:
            message += f" (after {retries} retries)"
        super().__init__(message)

EmptyMaskError

Bases: ValidationError

Raised when a mask contains no non-zero voxels.

Source code in src/lacuna/core/exceptions.py
class EmptyMaskError(ValidationError):
    """Raised when a mask contains no non-zero voxels."""

    def __init__(self, subject_id: str | None = None, detail: str | None = None):
        self.subject_id = subject_id
        if subject_id:
            message = f"Empty mask for '{subject_id}': mask contains no non-zero voxels. "
        else:
            message = "Empty mask: mask contains no non-zero voxels. "
        if detail:
            message += detail
        else:
            message += "Please ensure mask files contain valid lesion data."
        super().__init__(message)

FetchError

Bases: LacunaError

Base exception for all fetch/download errors.

Source code in src/lacuna/core/exceptions.py
class FetchError(LacunaError):
    """Base exception for all fetch/download errors."""

    pass

LacunaError

Bases: Exception

Base exception for all lacuna errors.

Source code in src/lacuna/core/exceptions.py
class LacunaError(Exception):
    """Base exception for all lacuna errors."""

    pass

NiftiLoadError

Bases: LacunaError, IOError

Raised when NIfTI file loading fails.

Source code in src/lacuna/core/exceptions.py
class NiftiLoadError(LacunaError, IOError):
    """Raised when NIfTI file loading fails."""

    pass

ProcessingError

Bases: FetchError

Raised when post-download processing fails.

Source code in src/lacuna/core/exceptions.py
class ProcessingError(FetchError):
    """Raised when post-download processing fails."""

    def __init__(self, operation: str, reason: str):
        self.operation = operation
        self.reason = reason
        message = f"Processing failed during '{operation}': {reason}"
        super().__init__(message)

ProvenanceError

Bases: LacunaError, RuntimeError

Raised when provenance tracking encounters issues.

Source code in src/lacuna/core/exceptions.py
class ProvenanceError(LacunaError, RuntimeError):
    """Raised when provenance tracking encounters issues."""

    pass

SpaceDetectionError

Bases: LacunaError

Raised when coordinate space cannot be detected from file.

Source code in src/lacuna/core/exceptions.py
class SpaceDetectionError(LacunaError):
    """Raised when coordinate space cannot be detected from file."""

    def __init__(self, filepath, attempted_methods):
        self.filepath = filepath
        self.attempted_methods = attempted_methods
        message = (
            f"Could not detect coordinate space for '{filepath}'. "
            f"Attempted methods: {', '.join(attempted_methods)}. "
            f"Please specify space explicitly using the 'space' parameter."
        )
        super().__init__(message)

SpaceMismatchError

Bases: ValidationError

Raised when declared space doesn't match detected space.

Source code in src/lacuna/core/exceptions.py
class SpaceMismatchError(ValidationError):
    """Raised when declared space doesn't match detected space."""

    def __init__(
        self, declared_space: str, detected_space: str | None, filepath, affine_difference: float
    ):
        self.declared_space = declared_space
        self.detected_space = detected_space
        self.filepath = filepath
        self.affine_difference = affine_difference

        message = (
            f"Space mismatch for '{filepath}': "
            f"declared='{declared_space}', detected='{detected_space}' "
            f"(affine difference: {affine_difference:.6f}). "
            f"Set require_match=False to override validation."
        )
        super().__init__(message)

SpatialMismatchError

Bases: ValidationError

Raised when spatial properties (affine, shape) don't match.

Source code in src/lacuna/core/exceptions.py
class SpatialMismatchError(ValidationError):
    """Raised when spatial properties (affine, shape) don't match."""

    pass

TransformDownloadError

Bases: LacunaError

Raised when transform file cannot be downloaded.

Source code in src/lacuna/core/exceptions.py
class TransformDownloadError(LacunaError):
    """Raised when transform file cannot be downloaded."""

    def __init__(self, source_space: str, target_space: str, reason: str):
        self.source_space = source_space
        self.target_space = target_space
        self.reason = reason
        message = (
            f"Failed to download transform from '{source_space}' to '{target_space}': {reason}. "
            f"Check network connection or download manually from TemplateFlow."
        )
        super().__init__(message)

TransformNotAvailableError

Bases: LacunaError

Raised when spatial transform is not available.

Source code in src/lacuna/core/exceptions.py
class TransformNotAvailableError(LacunaError):
    """Raised when spatial transform is not available."""

    def __init__(self, source_space: str, target_space: str, supported_transforms: list):
        self.source_space = source_space
        self.target_space = target_space
        message = (
            f"No transform available from '{source_space}' to '{target_space}'. "
            f"Supported transforms: {supported_transforms}"
        )
        super().__init__(message)

ValidationError

Bases: LacunaError, ValueError

Raised when data validation fails.

Source code in src/lacuna/core/exceptions.py
class ValidationError(LacunaError, ValueError):
    """Raised when data validation fails."""

    pass