AI systems fail constantly—network timeouts, malformed JSON, CUDA OOM errors, missing files. Exception handling with try/except lets you recover gracefully, log context, and keep pipelines running instead of crashing silently or spewing stack traces to end users.
After decorators (often combined with retry logic), structured error handling is the next skill for production-grade inference services and data ingestion scripts.
Learning Objectives
By the end of this lesson, students should be able to:
- Use
try,except,else, andfinallyblocks correctly. - Catch specific exception types rather than bare
except:. - Re-raise exceptions with
raisewhile preserving context. - Define custom exception classes for domain errors.
- Apply exception handling to API calls, file I/O, and model inference.
- Distinguish when to fail fast versus when to retry or skip bad records.
Introduction: Controlled Failure
When Python encounters an error it cannot handle, it raises an exception. Uncaught exceptions terminate the program. A try block lets you intercept specific failures and decide what happens next.
try:
risky_operation()
except SpecificError as exc:
handle(exc)
else:
# runs only if no exception occurred
...
finally:
# always runs (cleanup)
...
import requests
def fetch_embedding(text: str) -> list[float]:
try:
resp = requests.post(EMBED_URL, json={"text": text}, timeout=30)
resp.raise_for_status()
return resp.json()["embedding"]
except requests.Timeout:
raise RuntimeError(f"Embedding service timed out for: {text[:50]!r}")
except requests.HTTPError as exc:
raise RuntimeError(f"HTTP {exc.response.status_code}") from exc
Exception Hierarchy and Specificity
| Exception | Typical AI Cause | Handling Strategy |
|---|---|---|
FileNotFoundError | Missing dataset or checkpoint | Validate paths at startup |
json.JSONDecodeError | Malformed API / JSONL line | Skip record, log line number |
KeyError | Unexpected response schema | Schema validation, fallbacks |
torch.cuda.OutOfMemoryError | Batch too large | Reduce batch size, gradient checkpointing |
ValueError | Invalid hyperparameters | Fail fast with clear message |
except Exception: and ignore it.”
Reality: Swallowing errors hides data corruption and training bugs. Catch specific types, log context, and either recover meaningfully or re-raise. Never use bare except: (it catches KeyboardInterrupt too).
Custom Exceptions
class ModelNotLoadedError(RuntimeError):
"""Raised when inference runs before model weights are loaded."""
def predict(text):
if model is None:
raise ModelNotLoadedError("Call load_model() first")
...
Knowledge Check
- True/False:
finallyruns even ifreturnappears intry. Answer: True. - Short Answer: Why catch
requests.Timeoutseparately? Answer: Different recovery (retry/backoff) than HTTP errors. - Multiple Choice: Best practice for unknown errors in production: (a) bare except pass, (b) log and re-raise or return error response, (c) restart Python silently, (d) delete data. Answer: (b).
- Short Answer: When does the
elseclause ontryrun? Answer: Only if no exception occurred in thetryblock. - True/False: Bare
except:is safe because it only catches application errors. Answer: False—it also catchesKeyboardInterrupt; catch specific types instead. - Short Answer: Typical handling for
json.JSONDecodeErroron a JSONL line? Answer: Skip the record and log the line number. - Multiple Choice: CUDA OOM during training often suggests: (a) increase batch size, (b) reduce batch size / use checkpointing, (c) delete Python, (d) ignore it. Answer: (b).
- True/False: Custom exceptions like
ModelNotLoadedErrorcan clarify domain errors. Answer: True. - Short Answer: Why re-raise with
raise ... from exc? Answer: Preserve the original exception context for debugging. - Multiple Choice: Invalid hyperparameters should usually: (a) fail fast with a clear message, (b) be silently clipped, (c) crash the OS, (d) skip logging. Answer: (a).
Key Takeaways
- Use
try/exceptto handle expected failure modes without crashing. - Catch specific exceptions; log context; avoid silent swallowing.
- Custom exceptions clarify domain errors in AI services.
- Next: File I/O, where many exceptions originate.
Failure injection: Provide a JSONL file with one bad line. Students write a loader that logs and skips bad rows instead of aborting the entire import.
Recap: Catch specific exceptions, log context, and fail or retry deliberately; next, persist data with File I/O (JSON, CSV, text).