Exception Handling

SegnoMMS provides a comprehensive exception hierarchy for better error handling, debugging, and user experience. All exceptions inherit from SegnoMMSError and provide structured error information.

Exception Hierarchy

SegnoMMSError (base)
├── ConfigurationError
│   ├── ValidationError
│   ├── IntentValidationError
│   ├── PresetNotFoundError
│   └── IncompatibleConfigError
├── RenderingError
│   ├── MatrixError
│   │   ├── MatrixSizeError
│   │   └── MatrixBoundsError
│   ├── ShapeRenderingError
│   ├── SVGGenerationError
│   └── PerformanceError
├── IntentProcessingError
│   ├── UnsupportedIntentError
│   ├── IntentDegradationError
│   └── IntentTransformationError
├── ColorError
│   ├── InvalidColorFormatError
│   ├── ContrastRatioError
│   └── PaletteValidationError
├── CapabilityError
│   ├── FeatureNotSupportedError
│   └── CapabilityManifestError
└── DependencyError
    ├── MissingDependencyError
    └── OptionalFeatureUnavailableError

Base Exception

exception segnomms.exceptions.SegnoMMSError(message, code=None, details=None, suggestion=None)[source]

Bases: Exception

Base exception for all SegnoMMS errors.

Provides structured error information with: - Error codes for programmatic handling - Detailed messages for debugging - Suggestions for resolution - Additional context data

Parameters:
__init__(message, code=None, details=None, suggestion=None)[source]

Initialize SegnoMMS error.

Parameters:
  • message (str) – Human-readable error message

  • code (Optional[str]) – Stable error code for programmatic handling

  • details (Optional[Dict[str, Any]]) – Additional error context

  • suggestion (Optional[str]) – Suggestion for resolving the error

__str__()[source]

String representation of the error.

Return type:

str

to_dict()[source]

Convert error to dictionary for API responses.

Return type:

Dict[str, Any]

All SegnoMMS exceptions inherit from this base class and provide structured error information:

  • message: Human-readable error message

  • code: Stable error code for programmatic handling

  • details: Dictionary with additional error context

  • suggestion: Suggestion for resolving the error

Example Usage

from segnomms.intents import render_with_intents
from segnomms.exceptions import SegnoMMSError

try:
    # Some SegnoMMS operation
    result = render_with_intents(payload, intents)
except SegnoMMSError as e:
    print(f"Error [{e.code}]: {e.message}")
    if e.suggestion:
        print(f"Suggestion: {e.suggestion}")
    if e.details:
        print(f"Details: {e.details}")

    # Convert to dictionary for API responses
    error_dict = e.to_dict()

Configuration Errors

ValidationError

exception segnomms.exceptions.ValidationError(field, value, message, suggestion=None)[source]

Bases: ConfigurationError

Configuration validation error.

Used when configuration values fail validation rules.

Parameters:
  • field (str)

  • value (Any)

  • message (str)

  • suggestion (str | None)

__init__(field, value, message, suggestion=None)[source]

Initialize validation error.

Parameters:
  • field (str) – Configuration field that failed validation

  • value (Any) – The invalid value

  • message (str) – Description of validation failure

  • suggestion (Optional[str]) – How to fix the validation error

Raised when configuration values fail validation rules.

from segnomms.exceptions import ValidationError
from segnomms.config import RenderingConfig

try:
    config = RenderingConfig(scale=-1)  # Invalid scale
except ValidationError as e:
    print(f"Invalid {e.field}: {e.value}")
    print(f"Fix: {e.suggestion}")

IntentValidationError

exception segnomms.exceptions.IntentValidationError(intent_path, message, original_value=None, suggestion=None)[source]

Bases: ConfigurationError

Intent-specific validation error.

Used when intent configurations are invalid or incompatible.

Parameters:
  • intent_path (str)

  • message (str)

  • original_value (Any)

  • suggestion (str | None)

__init__(intent_path, message, original_value=None, suggestion=None)[source]

Initialize intent validation error.

Parameters:
  • intent_path (str) – Path to the invalid intent (e.g., “style.module_shape”)

  • message (str) – Description of the validation failure

  • original_value (Any) – The original intent value

  • suggestion (Optional[str]) – How to fix the intent

Raised for invalid intent configurations in the intent-based API.

from segnomms.exceptions import IntentValidationError
from segnomms.intents.models import IntentsConfig, StyleIntents

try:
    intents = IntentsConfig(
        style=StyleIntents(corner_radius=5.0)  # Out of valid range
    )
except IntentValidationError as e:
    print(f"Invalid intent at {e.intent_path}")
    print(f"Original value: {e.original_value}")

PresetNotFoundError

exception segnomms.exceptions.PresetNotFoundError(preset_name, available_presets)[source]

Bases: ConfigurationError

Raised when a requested preset doesn’t exist.

Parameters:
__init__(preset_name, available_presets)[source]

Initialize preset not found error.

Parameters:
  • preset_name (str) – Name of the missing preset

  • available_presets (List[str]) – List of available preset names

Raised when a requested configuration preset doesn’t exist.

IncompatibleConfigError

exception segnomms.exceptions.IncompatibleConfigError(option1, option2, message, suggestion=None)[source]

Bases: ConfigurationError

Raised when configuration options are incompatible.

Parameters:
  • option1 (str)

  • option2 (str)

  • message (str)

  • suggestion (str | None)

__init__(option1, option2, message, suggestion=None)[source]

Initialize incompatible configuration error.

Parameters:
  • option1 (str) – First conflicting option

  • option2 (str) – Second conflicting option

  • message (str) – Description of the conflict

  • suggestion (Optional[str]) – How to resolve the conflict

Raised when configuration options are incompatible with each other.

Rendering Errors

RenderingError

exception segnomms.exceptions.RenderingError(message, code=None, details=None, suggestion=None)[source]

Bases: SegnoMMSError

Base class for rendering-related errors.

Parameters:

Base class for all rendering-related errors.

MatrixError

exception segnomms.exceptions.MatrixError(message, code=None, details=None, suggestion=None)[source]

Bases: RenderingError

Base class for QR matrix-related errors.

Parameters:

Base class for QR matrix-related errors.

MatrixSizeError

exception segnomms.exceptions.MatrixSizeError(size, message=None)[source]

Bases: MatrixError

Raised when QR matrix has invalid size.

Parameters:
  • size (int)

  • message (str | None)

__init__(size, message=None)[source]

Initialize matrix size error.

Parameters:
  • size (int) – The invalid matrix size

  • message (Optional[str]) – Custom error message

Raised when QR matrix has invalid dimensions.

MatrixBoundsError

exception segnomms.exceptions.MatrixBoundsError(row, col, size)[source]

Bases: MatrixError

Raised when accessing matrix out of bounds.

Parameters:
__init__(row, col, size)[source]

Initialize matrix bounds error.

Parameters:
  • row (int) – Row index that was out of bounds

  • col (int) – Column index that was out of bounds

  • size (int) – Matrix size

Raised when attempting to access matrix positions out of bounds.

ShapeRenderingError

exception segnomms.exceptions.ShapeRenderingError(shape, message, details=None)[source]

Bases: RenderingError

Raised when shape rendering fails.

Parameters:
__init__(shape, message, details=None)[source]

Initialize shape rendering error.

Parameters:
  • shape (str) – The shape that failed to render

  • message (str) – Error description

  • details (Optional[Dict[str, Any]]) – Additional error context

Raised when shape rendering fails.

SVGGenerationError

exception segnomms.exceptions.SVGGenerationError(message, phase=None)[source]

Bases: RenderingError

Raised when SVG generation fails.

Parameters:
  • message (str)

  • phase (str | None)

__init__(message, phase=None)[source]

Initialize SVG generation error.

Parameters:
  • message (str) – Error description

  • phase (Optional[str]) – Phase where error occurred (e.g., “shape_generation”, “style_application”)

Raised when SVG generation fails.

PerformanceError

exception segnomms.exceptions.PerformanceError(metric, value, limit, message=None)[source]

Bases: RenderingError

Raised when performance limits are exceeded.

Parameters:
__init__(metric, value, limit, message=None)[source]

Initialize performance error.

Parameters:
  • metric (str) – Performance metric that was exceeded

  • value (Any) – Actual value

  • limit (Any) – Limit that was exceeded

  • message (Optional[str]) – Custom error message

Raised when performance limits are exceeded.

Intent Processing Errors

IntentProcessingError

exception segnomms.exceptions.IntentProcessingError(message, code=None, details=None, suggestion=None)[source]

Bases: SegnoMMSError

Base class for intent processing errors.

Parameters:

Base class for intent processing errors.

UnsupportedIntentError

exception segnomms.exceptions.UnsupportedIntentError(intent_path, feature, alternatives=None, planned_version=None)[source]

Bases: IntentProcessingError

Raised when an intent is not supported.

Parameters:
  • intent_path (str)

  • feature (str)

  • alternatives (List[str] | None)

  • planned_version (str | None)

__init__(intent_path, feature, alternatives=None, planned_version=None)[source]

Initialize unsupported intent error.

Parameters:
  • intent_path (str) – Path to unsupported intent

  • feature (str) – Description of unsupported feature

  • alternatives (Optional[List[str]]) – Alternative approaches

  • planned_version (Optional[str]) – Version when support is planned

Raised when an intent feature is not supported.

from segnomms.exceptions import UnsupportedIntentError

try:
    # Request unsupported feature
    intents = IntentsConfig(style=StyleIntents(module_shape="pyramid"))
except UnsupportedIntentError as e:
    print(f"Unsupported: {e.feature}")
    print(f"Alternatives: {e.alternatives}")
    print(f"Planned for: {e.planned_version}")

IntentDegradationError

exception segnomms.exceptions.IntentDegradationError(intent_path, requested, reason, applied=None)[source]

Bases: IntentProcessingError

Raised when intent degradation fails.

Parameters:
  • intent_path (str)

  • requested (Any)

  • reason (str)

  • applied (Any | None)

__init__(intent_path, requested, reason, applied=None)[source]

Initialize intent degradation error.

Parameters:
  • intent_path (str) – Path to degraded intent

  • requested (Any) – What was requested

  • reason (str) – Why degradation was necessary

  • applied (Optional[Any]) – What was applied instead (if anything)

Raised when intent degradation fails.

IntentTransformationError

exception segnomms.exceptions.IntentTransformationError(intent_path, message, original_value=None, error_details=None)[source]

Bases: IntentProcessingError

Raised when intent transformation fails.

Parameters:
  • intent_path (str)

  • message (str)

  • original_value (Any)

  • error_details (str | None)

__init__(intent_path, message, original_value=None, error_details=None)[source]

Initialize intent transformation error.

Parameters:
  • intent_path (str) – Path to the intent

  • message (str) – Error description

  • original_value (Any) – Original intent value

  • error_details (Optional[str]) – Detailed error information

Raised when intent transformation fails.

Color Errors

ColorError

exception segnomms.exceptions.ColorError(message, code=None, details=None, suggestion=None)[source]

Bases: SegnoMMSError

Base class for color-related errors.

Parameters:

Base class for color-related errors.

InvalidColorFormatError

exception segnomms.exceptions.InvalidColorFormatError(color, accepted_formats=None)[source]

Bases: ColorError

Raised when color format is invalid.

Parameters:
__init__(color, accepted_formats=None)[source]

Initialize invalid color format error.

Parameters:
  • color (str) – The invalid color value

  • accepted_formats (Optional[List[str]]) – List of accepted color formats

Raised when color format is invalid.

from segnomms.exceptions import InvalidColorFormatError

try:
    config = RenderingConfig(dark="not-a-color")
except InvalidColorFormatError as e:
    print(f"Invalid color: {e.color}")
    print(f"Accepted formats: {e.accepted_formats}")

ContrastRatioError

exception segnomms.exceptions.ContrastRatioError(foreground, background, ratio, required_ratio, standard='WCAG AA')[source]

Bases: ColorError

Raised when color contrast is insufficient.

Parameters:
__init__(foreground, background, ratio, required_ratio, standard='WCAG AA')[source]

Initialize contrast ratio error.

Parameters:
  • foreground (str) – Foreground color

  • background (str) – Background color

  • ratio (float) – Actual contrast ratio

  • required_ratio (float) – Required minimum ratio

  • standard (str) – Accessibility standard

Raised when color contrast is insufficient for accessibility or scanability.

from segnomms.exceptions import ContrastRatioError

try:
    # Colors with poor contrast
    config = RenderingConfig(dark="#888888", light="#999999")
except ContrastRatioError as e:
    print(f"Contrast too low: {e.ratio:.2f} < {e.required_ratio}")
    print(f"Standard: {e.standard}")

PaletteValidationError

exception segnomms.exceptions.PaletteValidationError(message, invalid_colors=None, validation_errors=None)[source]

Bases: ColorError

Raised when color palette validation fails.

Parameters:
  • message (str)

  • invalid_colors (List[str] | None)

  • validation_errors (List[str] | None)

__init__(message, invalid_colors=None, validation_errors=None)[source]

Initialize palette validation error.

Parameters:
  • message (str) – Error description

  • invalid_colors (Optional[List[str]]) – List of invalid colors

  • validation_errors (Optional[List[str]]) – List of validation error messages

Raised when color palette validation fails.

Capability Errors

CapabilityError

exception segnomms.exceptions.CapabilityError(message, code=None, details=None, suggestion=None)[source]

Bases: SegnoMMSError

Base class for capability-related errors.

Parameters:

Base class for capability-related errors.

FeatureNotSupportedError

exception segnomms.exceptions.FeatureNotSupportedError(feature, category=None, min_version=None)[source]

Bases: CapabilityError

Raised when a feature is not supported.

Parameters:
  • feature (str)

  • category (str | None)

  • min_version (str | None)

__init__(feature, category=None, min_version=None)[source]

Initialize feature not supported error.

Parameters:
  • feature (str) – The unsupported feature

  • category (Optional[str]) – Feature category

  • min_version (Optional[str]) – Minimum version required

Raised when a feature is not supported in the current version.

CapabilityManifestError

exception segnomms.exceptions.CapabilityManifestError(message, manifest_path=None)[source]

Bases: CapabilityError

Raised when capability manifest has issues.

Parameters:
  • message (str)

  • manifest_path (str | None)

__init__(message, manifest_path=None)[source]

Initialize capability manifest error.

Parameters:
  • message (str) – Error description

  • manifest_path (Optional[str]) – Path to manifest file

Raised when the capability manifest has issues.

Dependency Errors

DependencyError

exception segnomms.exceptions.DependencyError(message, code=None, details=None, suggestion=None)[source]

Bases: SegnoMMSError

Base class for dependency-related errors.

Parameters:

Base class for dependency-related errors.

MissingDependencyError

exception segnomms.exceptions.MissingDependencyError(dependency, feature=None, install_command=None)[source]

Bases: DependencyError

Raised when a required dependency is missing.

Parameters:
  • dependency (str)

  • feature (str | None)

  • install_command (str | None)

__init__(dependency, feature=None, install_command=None)[source]

Initialize missing dependency error.

Parameters:
  • dependency (str) – Name of missing dependency

  • feature (Optional[str]) – Feature that requires this dependency

  • install_command (Optional[str]) – Command to install dependency

Raised when a required dependency is missing.

from segnomms.exceptions import MissingDependencyError

try:
    # Feature requiring optional dependency
    result = some_feature_requiring_opencv()
except MissingDependencyError as e:
    print(f"Missing: {e.dependency}")
    print(f"Required for: {e.feature}")
    print(f"Install: {e.install_command}")

OptionalFeatureUnavailableError

exception segnomms.exceptions.OptionalFeatureUnavailableError(feature, reason, dependencies=None)[source]

Bases: DependencyError

Raised when an optional feature is unavailable.

Parameters:
__init__(feature, reason, dependencies=None)[source]

Initialize optional feature unavailable error.

Parameters:
  • feature (str) – The unavailable feature

  • reason (str) – Why it’s unavailable

  • dependencies (Optional[List[str]]) – Required dependencies

Raised when an optional feature is unavailable.

Error Handling Best Practices

Intent-Specific Error Patterns

When working with the intent-based API, use structured error handling for different scenarios:

from segnomms.intents import render_with_intents
from segnomms.exceptions import (
    IntentValidationError,
    UnsupportedIntentError,
    IntentDegradationError,
    IntentTransformationError,
    ContrastRatioError,
    SegnoMMSError
)

def robust_intent_processing(payload: str, intents: IntentsConfig):
    """Robust intent processing with comprehensive error handling."""
    try:
        result = render_with_intents(payload, intents)

        # Success path - check for warnings
        if result.has_warnings:
            handle_intent_warnings(result.warnings)

        return result

    except IntentValidationError as e:
        # Invalid intent structure or values
        print(f"Intent validation failed at {e.intent_path}")
        print(f"Invalid value: {e.original_value}")
        print(f"Expected: {e.details.get('expected_type', 'Valid value')}")
        if e.suggestion:
            print(f"Suggestion: {e.suggestion}")

        # Try with corrected intent
        return retry_with_fixed_intent(payload, intents, e)

    except UnsupportedIntentError as e:
        # Feature not available - graceful degradation
        print(f"Feature '{e.feature}' not supported")
        print(f"Available alternatives: {e.alternatives}")

        # Apply automatic fallback
        fallback_intents = apply_feature_fallback(intents, e.feature, e.alternatives)
        return render_with_intents(payload, fallback_intents)

    except IntentDegradationError as e:
        # Degradation system failed
        print(f"Degradation failed for: {e.details.get('failed_feature')}")
        print(f"Reason: {e.message}")

        # Use simplified configuration
        safe_intents = create_safe_fallback_intents(intents)
        return render_with_intents(payload, safe_intents)

    except ContrastRatioError as e:
        # Accessibility issue - adjust colors
        print(f"Contrast ratio {e.ratio:.2f} below required {e.required_ratio}")

        # Auto-adjust colors for accessibility
        adjusted_intents = improve_intent_contrast(intents, e.required_ratio)
        return render_with_intents(payload, adjusted_intents)

    except IntentTransformationError as e:
        # Internal transformation failed
        print(f"Intent transformation failed: {e.message}")
        print(f"Failed step: {e.details.get('transformation_step', 'Unknown')}")

        # Log for debugging and use minimal intents
        log_transformation_error(e, payload, intents)
        minimal_intents = create_minimal_intents()
        return render_with_intents(payload, minimal_intents)

    except SegnoMMSError as e:
        # Any other SegnoMMS error
        print(f"SegnoMMS error [{e.code}]: {e.message}")
        if e.suggestion:
            print(f"Suggestion: {e.suggestion}")

        # Log error details for analysis
        log_error_with_context(e, payload, intents)
        raise  # Re-raise for higher-level handling

Catching Specific Exceptions

Always catch the most specific exception type for better error recovery:

from segnomms.intents import render_with_intents
from segnomms.exceptions import (
    ValidationError,
    UnsupportedIntentError,
    ContrastRatioError,
    SegnoMMSError
)

try:
    result = render_with_intents(payload, intents)
except ValidationError as e:
    # Handle validation errors specifically
    fix_validation_error(e.field, e.value, e.suggestion)
except UnsupportedIntentError as e:
    # Gracefully degrade unsupported features
    fallback_to_alternative(e.alternatives)
except ContrastRatioError as e:
    # Adjust colors for better contrast
    improve_contrast(e.foreground, e.background, e.required_ratio)
except SegnoMMSError as e:
    # Handle any other SegnoMMS error
    log_error(e.code, e.message, e.details)

Production Error Recovery Strategies

Implement robust error recovery for production systems:

from typing import Optional, Dict, Any
import logging

class ProductionIntentHandler:
    """Production-ready intent handler with comprehensive error recovery."""

    def __init__(self, renderer):
        self.renderer = renderer
        self.logger = logging.getLogger(__name__)
        self.fallback_configs = self._load_fallback_configs()

    def process_with_recovery(
        self,
        payload: str,
        intents: IntentsConfig,
        max_retries: int = 3
    ) -> Dict[str, Any]:
        """Process intents with automatic error recovery."""

        for attempt in range(max_retries):
            try:
                result = self.renderer.render_with_intents(payload, intents)

                # Check for warnings that might indicate issues
                warnings = self._analyze_warnings(result.warnings)

                return {
                    "success": True,
                    "svg_content": result.svg_content,
                    "warnings": warnings,
                    "metrics": result.metrics.model_dump(),
                    "attempt": attempt + 1
                }

            except IntentValidationError as e:
                self.logger.warning(f"Intent validation error on attempt {attempt + 1}: {e}")
                intents = self._fix_validation_issues(intents, e)

            except UnsupportedIntentError as e:
                self.logger.warning(f"Unsupported feature on attempt {attempt + 1}: {e.feature}")
                intents = self._apply_feature_fallbacks(intents, e.feature, e.alternatives)

            except IntentDegradationError as e:
                self.logger.error(f"Degradation failed on attempt {attempt + 1}: {e}")
                intents = self._use_safe_fallback(attempt)

            except SegnoMMSError as e:
                self.logger.error(f"SegnoMMS error on attempt {attempt + 1}: {e.code}")
                if attempt == max_retries - 1:
                    # Last attempt - return error response
                    return {
                        "success": False,
                        "error": e.to_dict(),
                        "fallback_used": True,
                        "svg_content": self._generate_error_qr(payload)
                    }
                intents = self._use_safe_fallback(attempt)

        # All retries exhausted
        return {
            "success": False,
            "error": "MAX_RETRIES_EXCEEDED",
            "attempts": max_retries,
            "fallback_used": True,
            "svg_content": self._generate_minimal_qr(payload)
        }

    def _analyze_warnings(self, warnings: List[WarningInfo]) -> List[Dict[str, Any]]:
        """Analyze warnings for production monitoring."""
        analyzed = []
        for warning in warnings:
            analyzed.append({
                "code": warning.code,
                "severity": self._classify_warning_severity(warning),
                "detail": warning.detail,
                "actionable": warning.context.get("suggestion") is not None,
                "feature_impact": warning.context.get("feature_impact", "unknown")
            })
        return analyzed

    def _fix_validation_issues(
        self,
        intents: IntentsConfig,
        error: IntentValidationError
    ) -> IntentsConfig:
        """Automatically fix common validation issues."""
        # Clone intents for modification
        fixed_intents = intents.model_copy(deep=True)

        # Common fixes based on error path
        if "corner_radius" in error.intent_path:
            # Clamp corner radius to valid range
            setattr(fixed_intents, error.intent_path.split(".")[0], 0.3)
        elif "contrast" in error.intent_path:
            # Use high contrast colors
            if hasattr(fixed_intents, 'style'):
                fixed_intents.style.palette = {"fg": "#000000", "bg": "#FFFFFF"}

        return fixed_intents

    def _apply_feature_fallbacks(
        self,
        intents: IntentsConfig,
        unsupported_feature: str,
        alternatives: List[str]
    ) -> IntentsConfig:
        """Apply automatic feature fallbacks."""
        fallback_intents = intents.model_copy(deep=True)

        # Apply first available alternative
        if alternatives:
            # Logic to apply alternatives based on feature type
            if "shape" in unsupported_feature:
                fallback_intents.style.module_shape = alternatives[0]
            elif "frame" in unsupported_feature:
                fallback_intents.frame.shape = alternatives[0]

        return fallback_intents

    def _use_safe_fallback(self, attempt: int) -> IntentsConfig:
        """Use progressively simpler fallback configurations."""
        if attempt < len(self.fallback_configs):
            return self.fallback_configs[attempt]
        else:
            # Ultimate fallback - minimal configuration
            return IntentsConfig()

    def _generate_error_qr(self, payload: str) -> str:
        """Generate a basic QR code when all else fails."""
        try:
            return self.renderer.render_with_intents(
                payload,
                IntentsConfig()  # Minimal config
            ).svg_content
        except Exception:
            return self._generate_minimal_qr(payload)

    def _generate_minimal_qr(self, payload: str) -> str:
        """Generate the most basic QR code possible."""
        import segno
        qr = segno.make(payload)
        return qr.svg_inline()

Error Codes for API Integration

Use error codes for programmatic handling:

from segnomms.intents import render_with_intents

try:
    result = render_with_intents(payload, intents)
except SegnoMMSError as e:
    if e.code == "CONTRAST_RATIO_ERROR":
        # Adjust colors automatically
        payload.dark = "#000000"
        payload.light = "#FFFFFF"
        result = render_with_intents(payload, intents)
    elif e.code == "UNSUPPORTED_INTENT":
        # Remove unsupported features
        simplified_intents = simplify_intents(intents)
        result = render_with_intents(payload, simplified_intents)
    else:
        # Re-raise unknown errors
        raise

API Integration Examples

FastAPI Integration with Intent-Specific Error Handling

from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from typing import Dict, Any, Optional
from segnomms.intents import render_with_intents

app = FastAPI()

class QRGenerationRequest(BaseModel):
    payload: str
    intents: Dict[str, Any]

class QRGenerationResponse(BaseModel):
    success: bool
    svg_content: Optional[str] = None
    warnings: Optional[List[Dict[str, Any]]] = None
    error: Optional[Dict[str, Any]] = None
    metrics: Optional[Dict[str, Any]] = None
    degradation_used: bool = False

@app.post("/api/qr/generate", response_model=QRGenerationResponse)
async def generate_qr(request: QRGenerationRequest):
    """Generate QR code with comprehensive error handling."""
    try:
        intents_config = IntentsConfig.model_validate(request.intents)
        result = render_with_intents(request.payload, intents_config)

        # Success response with warnings
        return QRGenerationResponse(
            success=True,
            svg_content=result.svg_content,
            warnings=[warning.model_dump() for warning in result.warnings],
            metrics=result.metrics.model_dump(),
            degradation_used=len(result.warnings) > 0
        )

    except IntentValidationError as e:
        return JSONResponse(
            status_code=400,
            content=QRGenerationResponse(
                success=False,
                error={
                    "type": "intent_validation_error",
                    "code": e.code,
                    "message": e.message,
                    "intent_path": e.intent_path,
                    "invalid_value": e.original_value,
                    "suggestion": e.suggestion
                }
            ).model_dump()
        )

    except UnsupportedIntentError as e:
        # Try with fallback configuration
        try:
            fallback_intents = create_fallback_from_alternatives(
                intents_config, e.feature, e.alternatives
            )
            result = render_with_intents(request.payload, fallback_intents)

            return QRGenerationResponse(
                success=True,
                svg_content=result.svg_content,
                warnings=[{
                    "code": "FEATURE_FALLBACK_APPLIED",
                    "message": f"Feature '{e.feature}' not supported, used '{e.alternatives[0]}'",
                    "original_feature": e.feature,
                    "fallback_used": e.alternatives[0]
                }],
                degradation_used=True
            )

        except Exception:
            return JSONResponse(
                status_code=422,
                content=QRGenerationResponse(
                    success=False,
                    error={
                        "type": "unsupported_intent_error",
                        "code": e.code,
                        "message": e.message,
                        "unsupported_feature": e.feature,
                        "alternatives": e.alternatives,
                        "planned_version": e.planned_version
                    }
                ).model_dump()
            )

    except ContrastRatioError as e:
        return JSONResponse(
            status_code=400,
            content=QRGenerationResponse(
                success=False,
                error={
                    "type": "contrast_ratio_error",
                    "code": e.code,
                    "message": e.message,
                    "actual_ratio": e.ratio,
                    "required_ratio": e.required_ratio,
                    "accessibility_standard": e.standard,
                    "suggestion": "Use higher contrast colors or adjust the color palette"
                }
            ).model_dump()
        )

    except SegnoMMSError as e:
        return JSONResponse(
            status_code=500,
            content=QRGenerationResponse(
                success=False,
                error=e.to_dict()
            ).model_dump()
        )

Flask Integration with Error Monitoring

from flask import Flask, request, jsonify
import logging
from datetime import datetime

app = Flask(__name__)

# Configure error monitoring
error_logger = logging.getLogger('segnomms.errors')
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
))
error_logger.addHandler(handler)
error_logger.setLevel(logging.WARNING)

class ErrorMetrics:
    """Track error metrics for monitoring."""
    def __init__(self):
        self.error_counts = {}
        self.degradation_counts = {}

    def record_error(self, error_type: str, error_code: str):
        key = f"{error_type}:{error_code}"
        self.error_counts[key] = self.error_counts.get(key, 0) + 1

    def record_degradation(self, feature: str, fallback: str):
        key = f"{feature}->{fallback}"
        self.degradation_counts[key] = self.degradation_counts.get(key, 0) + 1

from segnomms.intents import render_with_intents
metrics = ErrorMetrics()

@app.route('/api/qr/generate', methods=['POST'])
def generate_qr():
    """Generate QR with comprehensive error tracking."""
    start_time = datetime.utcnow()
    data = request.get_json()

    try:
        payload = data.get('payload', '')
        intents_data = data.get('intents', {})

        intents = IntentsConfig.model_validate(intents_data)
        result = render_with_intents(payload, intents)

        # Track successful degradations for monitoring
        for warning in result.warnings:
            if warning.code == "FEATURE_DEGRADED":
                feature = warning.context.get('original_feature', 'unknown')
                fallback = warning.context.get('fallback_feature', 'unknown')
                metrics.record_degradation(feature, fallback)

        processing_time = (datetime.utcnow() - start_time).total_seconds() * 1000

        return jsonify({
            "success": True,
            "svg": result.svg_content,
            "warnings": [w.model_dump() for w in result.warnings],
            "metrics": {
                **result.metrics.model_dump(),
                "processing_time_ms": processing_time
            },
            "degradation_applied": len(result.warnings) > 0
        })

    except IntentValidationError as e:
        metrics.record_error("IntentValidationError", e.code)
        error_logger.warning(f"Intent validation error: {e.intent_path} = {e.original_value}")

        return jsonify({
            "success": False,
            "error": {
                "type": "validation_error",
                "code": e.code,
                "message": e.message,
                "field": e.intent_path,
                "invalid_value": e.original_value,
                "suggestion": e.suggestion
            }
        }), 400

    except UnsupportedIntentError as e:
        metrics.record_error("UnsupportedIntentError", e.code)
        error_logger.info(f"Unsupported feature requested: {e.feature}")

        return jsonify({
            "success": False,
            "error": {
                "type": "unsupported_feature",
                "code": e.code,
                "message": e.message,
                "feature": e.feature,
                "alternatives": e.alternatives,
                "will_be_supported": e.planned_version
            }
        }), 422

    except Exception as e:
        metrics.record_error("UnexpectedError", type(e).__name__)
        error_logger.error(f"Unexpected error: {e}", exc_info=True)

        return jsonify({
            "success": False,
            "error": {
                "type": "internal_error",
                "message": "An unexpected error occurred"
            }
        }), 500

@app.route('/api/metrics/errors', methods=['GET'])
def get_error_metrics():
    """Endpoint for monitoring error metrics."""
    return jsonify({
        "error_counts": metrics.error_counts,
        "degradation_counts": metrics.degradation_counts,
        "total_errors": sum(metrics.error_counts.values()),
        "total_degradations": sum(metrics.degradation_counts.values())
    })

Converting to API Responses

Use the to_dict() method for API responses:

from flask import jsonify
from segnomms.intents import render_with_intents

try:
    result = render_with_intents(payload, intents)
    return jsonify({"success": True, "svg": result.svg_content})
except SegnoMMSError as e:
    return jsonify({
        "success": False,
        "error": e.to_dict()
    }), 400

Custom Error Handling

Create custom handlers for different error types:

def handle_segnomms_error(error: SegnoMMSError) -> dict:
    """Convert SegnoMMS errors to consistent API responses."""
    response = {
        "success": False,
        "error_code": error.code,
        "message": error.message,
        "details": error.details
    }

    if error.suggestion:
        response["suggestion"] = error.suggestion

    # Add specific handling for different error types
    if isinstance(error, UnsupportedIntentError):
        response["alternatives"] = error.alternatives
        response["planned_version"] = error.planned_version
    elif isinstance(error, ContrastRatioError):
        response["contrast_info"] = {
            "actual_ratio": error.ratio,
            "required_ratio": error.required_ratio,
            "standard": error.standard
        }

    return response