Skip to content

Exceptions API

The exceptions module provides custom exception classes and error handling utilities for robust chatbot development. These exceptions help you handle various error scenarios gracefully and provide meaningful feedback to users.

Exception Handlers

The main exception handling utilities and custom exception classes.

Exception handling utilities.

Classes

LexError

LexError(message: str, error_code: str | None = None)

Bases: Exception

Base class for Lex-specific exceptions.

Source code in lex_helper/exceptions/handlers.py
def __init__(self, message: str, error_code: str | None = None):
    super().__init__(message)
    self.error_code = error_code

IntentNotFoundError

IntentNotFoundError(message: str, error_code: str | None = None)

Bases: LexError

Raised when an intent handler cannot be found.

Source code in lex_helper/exceptions/handlers.py
def __init__(self, message: str, error_code: str | None = None):
    super().__init__(message)
    self.error_code = error_code

ValidationError

ValidationError(message: str, error_code: str | None = None)

Bases: LexError

Raised when input validation fails.

Source code in lex_helper/exceptions/handlers.py
def __init__(self, message: str, error_code: str | None = None):
    super().__init__(message)
    self.error_code = error_code

SessionError

SessionError(message: str, error_code: str | None = None)

Bases: LexError

Raised when there's an issue with the session state.

Source code in lex_helper/exceptions/handlers.py
def __init__(self, message: str, error_code: str | None = None):
    super().__init__(message)
    self.error_code = error_code

Functions

handle_exceptions

handle_exceptions(ex: Exception, lex_request: LexRequest[Any], error_message: str | None = None) -> LexResponse[Any]

Handle exceptions and return appropriate Lex responses.

Parameters:

Name Type Description Default
ex Exception

The exception to handle

required
lex_request LexRequest[Any]

The original Lex request

required
error_message str | None

Error message (tries as message key first, then as direct string)

None

Returns:

Type Description
LexResponse[Any]

A Lex response with an appropriate error message

Examples:

Use default exception-specific messages

handle_exceptions(e, request)

Direct error message

handle_exceptions(e, request, error_message="Something went wrong")

Message key (automatically detected and localized)

handle_exceptions(e, request, error_message="general.error_generic")

Source code in lex_helper/exceptions/handlers.py
def handle_exceptions(ex: Exception, lex_request: LexRequest[Any], error_message: str | None = None) -> LexResponse[Any]:
    """Handle exceptions and return appropriate Lex responses.

    Args:
        ex: The exception to handle
        lex_request: The original Lex request
        error_message: Error message (tries as message key first, then as direct string)

    Returns:
        A Lex response with an appropriate error message

    Examples:
        # Use default exception-specific messages
        handle_exceptions(e, request)

        # Direct error message
        handle_exceptions(e, request, error_message="Something went wrong")

        # Message key (automatically detected and localized)
        handle_exceptions(e, request, error_message="general.error_generic")
    """
    # Default fallback message
    final_message = "I'm sorry, I encountered an error while processing your request. Please try again."

    # Handle error message - try as message key first, then use as direct string
    if error_message:
        try:
            from lex_helper import get_message

            # Try to get localized message (assumes it's a message key)
            final_message = get_message(error_message)
        except Exception:
            # If localization fails, use the error_message as a direct string
            final_message = error_message

    # Use exception-specific messages if no error message provided
    else:
        if isinstance(ex, IntentNotFoundError):
            final_message = "I'm not sure how to handle that request."
        elif isinstance(ex, ValidationError):
            final_message = str(ex) or "Invalid input provided."
        elif isinstance(ex, SessionError):
            final_message = "There was an issue with your session. Please start over."
        elif isinstance(ex, ValueError):
            final_message = "Invalid value provided."

    # Create error response
    lex_response: LexResponse[Any] = LexResponse(
        sessionState=SessionState(
            dialogAction=DialogAction(
                type="Close",
            ),
            intent=lex_request.sessionState.intent,
            originatingRequestId=lex_request.sessionId,
            sessionAttributes=lex_request.sessionState.sessionAttributes or {},
        ),
        messages=[LexPlainText(content=final_message, contentType="PlainText")],
        requestAttributes={},
    )
    return lex_response

safe_execute

safe_execute(func: Callable[P, R], *args: args, **kwargs: kwargs) -> R | None

Safely execute a function and handle exceptions.

Parameters:

Name Type Description Default
func Callable[P, R]

Function to execute

required
*args args

Positional arguments for the function

()
**kwargs kwargs

Keyword arguments for the function

{}

Returns:

Type Description
R | None

Function result or None if execution fails

Example

result = safe_execute(lambda x: int(x), "123") 123 result = safe_execute(lambda x: int(x), "abc") None

Source code in lex_helper/exceptions/handlers.py
def safe_execute(func: Callable[P, R], *args: P.args, **kwargs: P.kwargs) -> R | None:
    """Safely execute a function and handle exceptions.

    Args:
        func: Function to execute
        *args: Positional arguments for the function
        **kwargs: Keyword arguments for the function

    Returns:
        Function result or None if execution fails

    Example:
        >>> result = safe_execute(lambda x: int(x), "123")
        123
        >>> result = safe_execute(lambda x: int(x), "abc")
        None
    """
    try:
        return func(*args, **kwargs)
    except Exception:
        return None

with_error_handling

with_error_handling(error_type: type[Exception], error_message: str) -> Callable[[Callable[P, R]], Callable[P, R]]

Decorator to handle specific exceptions with custom messages.

Parameters:

Name Type Description Default
error_type type[Exception]

Type of exception to catch

required
error_message str

Message to use when exception occurs

required

Returns:

Type Description
Callable[[Callable[P, R]], Callable[P, R]]

Decorated function

Example

@with_error_handling(ValueError, "Invalid number") ... def parse_int(s: str) -> int: ... return int(s)

Source code in lex_helper/exceptions/handlers.py
def with_error_handling(error_type: type[Exception], error_message: str) -> Callable[[Callable[P, R]], Callable[P, R]]:
    """Decorator to handle specific exceptions with custom messages.

    Args:
        error_type: Type of exception to catch
        error_message: Message to use when exception occurs

    Returns:
        Decorated function

    Example:
        >>> @with_error_handling(ValueError, "Invalid number")
        ... def parse_int(s: str) -> int:
        ...     return int(s)
    """

    def decorator(func: Callable[P, R]) -> Callable[P, R]:
        def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
            try:
                return func(*args, **kwargs)
            except error_type as e:
                raise LexError(error_message) from e

        return wrapper

    return decorator

Exception Hierarchy

The lex-helper exceptions follow a clear hierarchy for easy handling:

Exception
└── LexHelperError (base for all lex-helper exceptions)
    ├── IntentNotFoundError
    ├── ValidationError
    └── IntegrationError

Usage Examples

Basic Exception Handling

from lex_helper.exceptions.handlers import handle_exceptions, IntentNotFoundError
from lex_helper.core.types import LexRequest

try:
    # Your intent handling code
    result = process_intent(lex_request)
except IntentNotFoundError as e:
    # Handle missing intent
    error_response = handle_exceptions(e, lex_request)
    return error_response

Automatic Exception Handling

The LexHelper class can automatically handle exceptions when configured:

from lex_helper import LexHelper, Config

config = Config(
    session_attributes=MySessionAttributes(),
    auto_handle_exceptions=True,  # Enable automatic exception handling
    error_message="Sorry, something went wrong. Please try again."
)

lex_helper = LexHelper(config)

Custom Error Messages

You can provide custom error messages or message keys:

# Using a custom message
config = Config(
    session_attributes=MySessionAttributes(),
    auto_handle_exceptions=True,
    error_message="We're experiencing technical difficulties. Please try again later."
)

# Using a message key (requires MessageManager)
config = Config(
    session_attributes=MySessionAttributes(),
    auto_handle_exceptions=True,
    error_message="error.technical_difficulty"  # Will be looked up in messages
)

Exception Context

Exceptions include context about the request and error:

try:
    # Process request
    pass
except IntentNotFoundError as e:
    logger.error(f"Intent not found: {e.intent_name}")
    logger.error(f"Available intents: {e.available_intents}")
    # Handle gracefully

Error Response Format

All exception handlers return properly formatted Lex responses that:

  • Maintain session state
  • Include appropriate error messages
  • Are formatted for the correct channel
  • Preserve conversation context where possible

Best Practices

1. Use Automatic Exception Handling

Enable automatic exception handling in production to ensure users always receive a response:

config = Config(
    auto_handle_exceptions=True,
    error_message="I'm sorry, I encountered an error. Please try again."
)

2. Provide Meaningful Error Messages

Use clear, user-friendly error messages that help users understand what went wrong:

# Good: Clear and actionable
error_message = "I couldn't find that flight. Please check the flight number and try again."

# Avoid: Technical jargon
error_message = "FlightNotFoundError: Invalid flight identifier in database query"

3. Log Errors for Debugging

Always log exceptions for debugging while showing user-friendly messages:

import logging

logger = logging.getLogger(__name__)

try:
    # Process request
    pass
except Exception as e:
    logger.exception("Error processing request")  # Logs full stack trace
    # Return user-friendly response

4. Handle Specific Exceptions

Catch specific exceptions when you can provide targeted handling:

try:
    # Process intent
    pass
except IntentNotFoundError:
    return "I didn't understand that. Can you try rephrasing?"
except ValidationError:
    return "Please check your input and try again."
except Exception:
    return "Something went wrong. Please try again later."

Next: Explore the Examples for practical usage patterns.