"""Typed exceptions for GCMD classifier deterministic components.""" class GCMDClassifierError(Exception): """Base exception for GCMD classifier errors.""" class VocabularyError(GCMDClassifierError): """Base exception for vocabulary loading and indexing errors.""" class MalformedHierarchyError(VocabularyError): """Raised when a hierarchy node is missing required structure or fields.""" class DuplicateUUIDError(VocabularyError): """Raised when the hierarchy contains the same UUID more than once.""" class DuplicateCanonicalPathError(VocabularyError): """Raised when one canonical path is assigned to multiple UUIDs.""" class InvalidHierarchyTransitionError(VocabularyError): """Raised when a node appears under an invalid hierarchy parent level.""" class VocabularyLookupError(VocabularyError): """Raised when a requested vocabulary concept or relationship is missing.""" class ArticleError(GCMDClassifierError): """Base exception for article loading and validation errors.""" class ArticleFileNotFoundError(ArticleError): """Raised when an article source file does not exist.""" class ArticleJSONDecodeError(ArticleError): """Raised when an article source file contains invalid JSON.""" class ArticleTopLevelTypeError(ArticleError): """Raised when an article source file is not a top-level JSON list.""" class ModelError(GCMDClassifierError): """Base exception for model provider and structured-output errors.""" class RetryableModelError(ModelError): """Raised for temporary model failures eligible for retry.""" class NonRetryableModelError(ModelError): """Raised for model failures that should not be retried.""" class StructuredModelResponseError(NonRetryableModelError): """Raised when a model response cannot be validated into the requested schema.""" class UnknownCandidateIDError(NonRetryableModelError): """Reserved for later routing stages that validate selected candidate IDs.""" class ModelRetriesExhaustedError(ModelError): """Raised when retryable model failures exceed the configured retry budget.""" def __init__(self, message: str, *, retry_count: int) -> None: super().__init__(message) self.retry_count = retry_count