Domain-Specific Error Types

Concrete error classes for common failure scenarios in library ecosystems

Domain-Specific Errors

These concrete error types provide semantic meaning for common failure scenarios across the library ecosystem. Each error type has sensible defaults for severity and retry behavior, but these can be overridden when needed.

ValidationError

For data validation failures, schema validation, and constraint violations.


ValidationError


def ValidationError(
    message:str, # User-friendly error message
    debug_info:Optional=None, # Optional developer details
    context:Optional=None, # Structured error context
    severity:ErrorSeverity=<ErrorSeverity.ERROR: 'error'>, # Error severity level
    is_retryable:bool=False, # Validation errors typically need fixes, not retries
    cause:Optional=None, # Original exception if chaining
    validation_errors:Optional=None, # Structured validation details
):

Raised when validation fails.

Example: ValidationError

# Schema validation failure
error1 = ValidationError(
    message="Plugin configuration is invalid",
    debug_info="Field 'model_id' is required but missing",
    context=ErrorContext(plugin_id="whisper_large", operation="validate_config"),
    validation_errors={
        "model_id": "required field missing",
        "temperature": "must be between 0.0 and 1.0"
    }
)

print("Validation Error:", error1.get_user_message())
print("Details:", error1.validation_errors)
Validation Error: Plugin configuration is invalid
Details: {'model_id': 'required field missing', 'temperature': 'must be between 0.0 and 1.0'}
# Resource validation failure
error2 = ValidationError(
    message="GPU unavailable for job execution",
    debug_info="GPU 0 in use by external process (PID 12345)",
    context=ErrorContext(
        job_id="job-123",
        plugin_id="whisper_large",
        operation="validate_resources",
        extra={"gpu_id": 0, "required_memory_mb": 8192}
    )
)

print("\nResource Validation:", error2.get_user_message())
print("Debug:", error2.get_debug_message())

Resource Validation: GPU unavailable for job execution
Debug: GPU unavailable for job execution | Debug: GPU 0 in use by external process (PID 12345)

ConfigurationError

For configuration file issues, missing settings, and config loading/saving failures.


ConfigurationError


def ConfigurationError(
    message:str, # User-friendly error message
    debug_info:Optional=None, # Optional developer details
    context:Optional=None, # Structured error context
    severity:ErrorSeverity=<ErrorSeverity.ERROR: 'error'>, # Error severity level
    is_retryable:bool=False, # Config issues usually need manual fixes
    cause:Optional=None, # Original exception if chaining
    config_path:Optional=None, # Path to problematic config file
):

Raised when configuration operations fail.

Example: ConfigurationError

# Config file not found
error3 = ConfigurationError(
    message="Configuration file not found",
    debug_info="Expected config at /home/user/.config/app/settings.json",
    context=ErrorContext(operation="load_config"),
    config_path="/home/user/.config/app/settings.json"
)

print("Config Error:", error3.get_user_message())
print("Path:", error3.config_path)
Config Error: Configuration file not found
Path: /home/user/.config/app/settings.json
# Config parse error with chaining
import json

try:
    json.loads('{"broken": json}')
except json.JSONDecodeError as e:
    error4 = ConfigurationError(
        message="Failed to parse configuration file",
        debug_info="JSON syntax error in config file",
        context=ErrorContext(plugin_id="whisper_base", operation="load_plugin_config"),
        config_path="configs/whisper_base.json",
        cause=e
    )
    
    print("\nConfig Parse Error:", error4.get_user_message())
    print("Debug:", error4.get_debug_message())

Config Parse Error: Failed to parse configuration file
Debug: Failed to parse configuration file | Debug: JSON syntax error in config file | Caused by: JSONDecodeError: Expecting value: line 1 column 12 (char 11)

ResourceError

For resource conflicts and availability issues (GPU busy, insufficient memory, etc.).


ResourceError


def ResourceError(
    message:str, # User-friendly error message
    debug_info:Optional=None, # Optional developer details
    context:Optional=None, # Structured error context
    severity:ErrorSeverity=<ErrorSeverity.WARNING: 'warning'>, # Often transient
    is_retryable:bool=True, # Resource conflicts may be temporary
    cause:Optional=None, # Original exception if chaining
    resource_type:Optional=None, # "GPU", "Memory", "Disk", etc.
    suggested_action:Optional=None, # Guidance for resolution
):

Raised when resource conflicts or unavailability prevent operation.

Example: ResourceError

# GPU conflict
error5 = ResourceError(
    message="GPU currently unavailable",
    debug_info="GPU 0 in use by transcription worker (PID 54321)",
    context=ErrorContext(
        job_id="job-456",
        operation="start_job",
        extra={"gpu_id": 0, "conflicting_worker_pid": 54321}
    ),
    resource_type="GPU",
    suggested_action="Wait for current job to complete or cancel it",
    is_retryable=True
)

print("Resource Error:", error5.get_user_message())
print("Resource type:", error5.resource_type)
print("Suggested action:", error5.suggested_action)
print("Retryable:", error5.is_retryable)
Resource Error: GPU currently unavailable
Resource type: GPU
Suggested action: Wait for current job to complete or cancel it
Retryable: True
# Memory error
error6 = ResourceError(
    message="Insufficient memory to load model",
    debug_info="Required: 8GB, Available: 2GB",
    context=ErrorContext(
        plugin_id="whisper_large",
        operation="load_model",
        extra={"required_gb": 8, "available_gb": 2}
    ),
    severity=ErrorSeverity.ERROR,
    resource_type="Memory",
    suggested_action="Use a smaller model or free up system memory",
    is_retryable=False  # Won't fix itself
)

print("\nMemory Error:", error6.get_user_message())
print("Suggested action:", error6.suggested_action)

Memory Error: Insufficient memory to load model
Suggested action: Use a smaller model or free up system memory

PluginError

For plugin discovery, loading, initialization, and execution failures.


PluginError


def PluginError(
    message:str, # User-friendly error message
    debug_info:Optional=None, # Optional developer details
    context:Optional=None, # Structured error context
    severity:ErrorSeverity=<ErrorSeverity.ERROR: 'error'>, # Error severity level
    is_retryable:bool=False, # Plugin errors usually need fixes
    cause:Optional=None, # Original exception if chaining
    plugin_id:Optional=None, # ID of problematic plugin
    plugin_name:Optional=None, # Name of problematic plugin
):

Raised when plugin operations fail.

Example: PluginError

# Plugin not found
error7 = PluginError(
    message="Plugin not found",
    debug_info="No plugin registered with ID 'transcription_whisper_huge'",
    context=ErrorContext(operation="load_plugin"),
    plugin_id="transcription_whisper_huge"
)

print("Plugin Error:", error7.get_user_message())
print("Plugin ID:", error7.plugin_id)
Plugin Error: Plugin not found
Plugin ID: transcription_whisper_huge
# Plugin initialization failure with cause
try:
    raise ImportError("No module named 'torch'")
except ImportError as e:
    error8 = PluginError(
        message="Failed to initialize plugin",
        debug_info="Missing required dependency: torch",
        context=ErrorContext(
            plugin_id="whisper_large",
            operation="initialize"
        ),
        plugin_id="whisper_large",
        plugin_name="Whisper Large",
        cause=e
    )
    
    print("\nPlugin Init Error:", error8.get_user_message())
    print("Plugin name:", error8.plugin_name)
    print("Debug:", error8.get_debug_message())

Plugin Init Error: Failed to initialize plugin
Plugin name: Whisper Large
Debug: Failed to initialize plugin | Debug: Missing required dependency: torch | Caused by: ImportError: No module named 'torch'

WorkerError

For worker process failures, communication errors, and job execution issues.


WorkerError


def WorkerError(
    message:str, # User-friendly error message
    debug_info:Optional=None, # Optional developer details
    context:Optional=None, # Structured error context
    severity:ErrorSeverity=<ErrorSeverity.ERROR: 'error'>, # Error severity level
    is_retryable:bool=True, # Worker errors may be transient
    cause:Optional=None, # Original exception if chaining
    worker_type:Optional=None, # "transcription", "llm", etc.
    job_id:Optional=None, # Job that failed
):

Raised when worker process operations fail.

Example: WorkerError

# Worker crash
error9 = WorkerError(
    message="Worker process terminated unexpectedly",
    debug_info="Worker PID 98765 exited with code -11 (SIGSEGV)",
    context=ErrorContext(
        job_id="job-789",
        worker_pid=98765,
        operation="execute_job"
    ),
    severity=ErrorSeverity.CRITICAL,
    worker_type="transcription",
    job_id="job-789",
    is_retryable=True  # Worker can be restarted
)

print("Worker Error:", error9.get_user_message())
print("Worker type:", error9.worker_type)
print("Job ID:", error9.job_id)
print("Retryable:", error9.is_retryable)
Worker Error: Worker process terminated unexpectedly
Worker type: transcription
Job ID: job-789
Retryable: True
# Worker timeout
error10 = WorkerError(
    message="Worker operation timed out",
    debug_info="No response from worker after 30 seconds",
    context=ErrorContext(
        worker_pid=11111,
        operation="reload_plugin",
        extra={"timeout_seconds": 30}
    ),
    severity=ErrorSeverity.WARNING,
    worker_type="transcription",
    is_retryable=True
)

print("\nWorker Timeout:", error10.get_user_message())
print("Debug:", error10.get_debug_message())

Worker Timeout: Worker operation timed out
Debug: Worker operation timed out | Debug: No response from worker after 30 seconds

Summary: When to Use Each Error Type

Error Type Use When Default Retryable Example
ValidationError Data/schema validation fails No Plugin config invalid, GPU requirements not met
ConfigurationError Config file issues No Config file not found, parse error
ResourceError Resource conflicts/unavailable Yes GPU busy, out of memory
PluginError Plugin operations fail No Plugin not found, init failed
WorkerError Worker process issues Yes Worker crashed, communication timeout

All inherit from BaseError, so you can catch them generically or specifically as needed.

Example: Catching Multiple Error Types

def handle_errors():
    """Demonstrate catching different error types."""
    scenarios = [
        ValidationError("Config invalid", context=ErrorContext(operation="validate")),
        ResourceError("GPU busy", resource_type="GPU", is_retryable=True),
        WorkerError("Worker crashed", worker_type="transcription")
    ]
    
    for error in scenarios:
        try:
            raise error
        except ValidationError as e:
            print(f"Validation failed: {e.get_user_message()}")
            print(f"  → Action: Fix the input and try again\n")
        except ResourceError as e:
            print(f"Resource issue: {e.get_user_message()}")
            if e.is_retryable:
                print(f"  → Action: Retry after {e.resource_type} becomes available\n")
        except WorkerError as e:
            print(f"Worker issue: {e.get_user_message()}")
            print(f"  → Action: Restart {e.worker_type} worker\n")
        except BaseError as e:
            # Catch-all for any other error types
            print(f"Unexpected error: {e.get_user_message()}\n")

handle_errors()
Validation failed: Config invalid
  → Action: Fix the input and try again

Resource issue: GPU busy
  → Action: Retry after GPU becomes available

Worker issue: Worker crashed
  → Action: Restart transcription worker