Exception Handling

MEDIUM3 min readby AdminJune 20, 2026History
0.0|0 ratingsLog in to rate

Exception handling is the mechanism of responding to anomalies (exceptions) during execution. In Python, it is done via `try`, `except`, `else`, `finally`, and ...

#ai-engineering#course#exception

Definition

Exception handling is the mechanism of responding to anomalies (exceptions) during execution. In Python, it is done via try, except, else, finally, and customized raise declarations.

Why It Exists

Third-party APIs fail regularly due to rate limiting (429), timeouts, network interruptions, or raw service crashes. A production AI backend must intercept these exceptions gracefully, log them, retry the execution, or switch to backup providers instead of crashing.

How It Works

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
EXCEPTION PIPELINE
                     ┌────────────────┐
                     │ Try block code │ (Execute request)
                     └───────┬────────┘
                             │
            ┌────────────────┴────────────────┐
     [Exception Raised?]               [No Error Raised]
            │                                 │
     ┌──────▼──────┐                   ┌──────▼──────┐
     │ Except Block│ (Log/Recover)     │ Else Block  │ (Proceed)
     └──────┬──────┘                   └──────┬──────┘
            │                                 │
            └───────────────┬─────────────────┘
                            ▼
                    ┌───────────────┐
                    │ Finally Block │ (Clean up resources/Close files)
                    └───────────────┘

1. **Catching Specific Errors**: Never use a bare `except:`. This catches system exits (`KeyboardInterrupt`), which makes terminating the app impossible.
2. **Finally Block Execution**: The `finally` block runs regardless of whether an exception occurred, ensuring files, database connections, and HTTP sockets are closed safely.

Real-World Example

Example

In Cursor, if the primary backend fails to connect to Claude, the system catches the connection error and raises an informative popup notification in the editor asking you to check your network connection, rather than freezing the editing workspace.

Python Example

Example

Here is a production pattern for safe third-party API calling with structured error logging and recovery:

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import logging

class LLMAPIError(Exception):
    """Base exception for all LLM API operations."""
    pass

class RateLimitError(LLMAPIError):
    """Exception raised when API returns 429 status."""
    pass

def call_mock_gateway(url: str, request_data: dict) -> dict:
    # Represents mock network gateway check
    if not url:
        raise ConnectionRefusedError("Unable to locate endpoint target.")
    if "data" not in request_data:
        raise ValueError("Missing 'data' key payload.")
    return {"status": "success", "tokens": 120}

def safe_api_runner(url: str, data: dict) -> dict:
    """Wrapper that catches low-level exceptions and raises custom domain errors."""
    try:
        response = call_mock_gateway(url, data)
    except ConnectionRefusedError as e:
        logging.error(f"Network failure calling endpoint {url}: {e}")
        raise LLMAPIError("Internal model connection failed.") from e
    except ValueError as e:
        logging.error(f"Invalid payload config: {e}")
        raise LLMAPIError("Corrupt request format.") from e
    except Exception as e:
        logging.error(f"Unexpected error: {e}")
        raise LLMAPIError("An unknown system error occurred.") from e
    else:
        logging.info("Request completed successfully.")
        return response
    finally:
        logging.info("Cleaning up open connection channels.")

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    try:
        safe_api_runner("http://api.model.com", {}) # Trigger ValueError
    except LLMAPIError as e:
        print(f"Intercepted Custom Exception: {e}")

Interview Questions

  • Beginner: Why is using a bare except: generally considered a bad practice?
  • Intermediate: What is the difference between except Exception as e: and custom user-defined exceptions?
  • Advanced: Explain the purpose of raise ... from e (Exception Chaining).

Interview Answers

  • Beginner: A bare except: catches every exception, including system signals like SystemExit or KeyboardInterrupt. This blocks the developer from terminating the running script via Ctrl+C in the terminal.
  • Intermediate: except Exception as e: catches all standard Python runtime exceptions. Custom exceptions inherit from Exception and allow your application to categorize domain-specific failures (like InsufficentTokenBalanceError), making exception handling more granular.
  • Advanced: Exception Chaining (raise CustomError from e) preserves the stack trace of the original underlying exception (e) while raising a cleaner high-level error (CustomError). This helps developers trace the root cause during debugging.

Common Mistakes

  • Swallowing exceptions: Catching an error and doing nothing: except: pass. This hides bugs, making system failures impossible to debug. At a minimum, log the exception.

Assignment

Write a function that parses a string to float. If a ValueError is raised, return a default value of 0.0. If any other error occurs, re-raise it.


Discussion

Join the discussion! Sign in to leave comments and ask questions.

Loading discussion...