Skip to main content

Overview

tif1 implements a structured exception hierarchy designed for clarity and debuggability when errors occur. Every exception in the library inherits from the base TIF1Error class. Each exception includes contextual information that shows what went wrong and why. The exception system is designed with several key principles:
  • Structured Context: Every exception carries a context dictionary with relevant metadata (year, event, driver, URL, etc.)
  • Clear Hierarchy: Exceptions are organized in a logical tree structure. Catch errors at the appropriate level of specificity
  • Actionable Messages: Error messages are automatically constructed with relevant details to aid debugging
  • Type Safety: All exceptions are properly typed for IDE autocomplete and type checking
  • Graceful Degradation: The design encourages handling errors gracefully rather than crashing
This guide covers every exception type in detail. It explains when each exception is raised, what context it provides, and how to handle it.

Exception Hierarchy

The exception hierarchy allows errors to be caught at different levels of specificity. Catch broad categories (like TIF1Error for any library error) or specific exceptions (like DriverNotFoundError for missing drivers).

Catching Strategy

The hierarchy allows flexible error handling:

Base Exception

TIF1Error

The root exception class for all tif1 errors. Every exception in the library inherits from this class. A single except clause on TIF1Error catches all tif1-specific errors. Signature:
Attributes:
  • message (str): Human-readable error message describing what went wrong
  • context (dict[str, Any]): Dictionary containing structured contextual information about the error
Key Features:
  • All context keyword arguments are automatically stored in the context dictionary
  • The message is both stored as an attribute and passed to the base Exception class
  • Subclasses can add their own context keys while preserving the base functionality
When Raised:
  • Never raised directly; always use a more specific subclass
  • Used as a catch-all to handle any tif1 error
Example - Basic Usage:
Example - Logging with Context:
Example - Custom Error Handling:

Data Errors

DataNotFoundError

Raised when requested F1 data is not available in the CDN or cache. This is one of the most common exceptions. It typically occurs when requesting data for sessions that have not happened yet. It also occurs for historical sessions where data was never collected. Signature:
Context Keys:
  • year (int | None): The requested year (for example, 2024)
  • event (str | None): The requested event/Grand Prix name (for example, “Monaco Grand Prix”)
  • session (str | None): The requested session type (for example, “Race”, “Qualifying”, “FP1”)
  • Additional context from **context kwargs
When Raised:
  • HTTP 404 responses from the CDN (data file does not exist)
  • Requesting future sessions that have not occurred yet
  • Requesting historical data that was never collected or published
  • Requesting data for cancelled sessions (for example, 2020 Australian GP)
  • Invalid year/event/session combinations
Common Scenarios:
  1. Future Sessions: Requesting data for races that have not happened yet
  2. Historical Gaps: Some older seasons have incomplete data coverage
  3. Cancelled Events: Sessions that were scheduled but cancelled
  4. Invalid Combinations: Requesting “Sprint” for a non-sprint weekend
Example - Basic Handling:
Example - Checking Data Availability:
Example - Fallback to Alternative Session:
Example - Batch Processing with Error Tracking:

DriverNotFoundError

Raised when attempting to access a driver that does not exist in the session. This is a subclass of DataNotFoundError. It typically occurs due to typos in driver codes. It also occurs when requesting drivers who did not participate in the session. Signature:
Context Keys:
  • driver (str): The requested driver code (for example, “VER”, “HAM”)
  • year (int | None): Session year (if provided in context)
  • event (str | None): Event name (if provided in context)
  • session (str | None): Session name (if provided in context)
When Raised:
  • Calling session.get_driver("XXX") with an invalid driver code
  • Driver code typos (for example, “VET” instead of “VER”)
  • Requesting a driver who did not participate in that specific session
  • Driver retired/withdrew before the session
Common Causes:
  1. Typos: “HAM” vs “HAN”, “VER” vs “VET”
  2. Wrong Session: Driver participated in practice but not qualifying
  3. Historical Changes: Driver codes changed between seasons
  4. Case Sensitivity: Driver codes are case-sensitive
Example - Basic Handling:
Example - Fuzzy Driver Matching:
Example - Safe Driver Access:
Example - Validating Driver List:
Example - Batch Driver Analysis:
--- ### LapNotFoundError Raised when attempting to access a specific lap number that does not exist for a driver. This is a subclass of DataNotFoundError. It typically occurs when requesting lap numbers beyond what the driver completed. It also occurs when requesting laps that were invalidated or deleted. Signature:
Context Keys:
  • lap_number (int | None): The requested lap number (for example, 1, 50, 999)
  • driver (str | None): The driver code for whom the lap was requested (for example, “VER”, “HAM”)
  • Additional context from **context kwargs
When Raised:
  • Calling driver.get_lap(N) where N exceeds the driver’s total lap count
  • Requesting lap 0 or negative lap numbers
  • Requesting laps that were deleted due to track limits violations
  • Requesting laps from drivers who retired early in the session
  • Accessing laps before the driver started (for example, lap 1 when driver started from pit lane on lap 2)
Common Scenarios:
  1. Out of Range: Requesting lap 60 when the driver only completed 45 laps
  2. Early Retirement: Driver crashed on lap 10, requesting lap 20
  3. Invalid Laps: Lap was deleted due to track limits or red flag
  4. Formation Laps: Requesting lap 0 (formation lap) which may not be recorded
Example - Basic Handling:
Example - Safe Lap Access:
Example - Validating Lap Range:
Example - Finding Last Valid Lap:
Example - Analyzing Lap Completion:
Example - Handling Retired Drivers:

Network Errors

NetworkError

Raised when HTTP network requests fail after all retries and CDN fallback mechanisms are exhausted. This exception indicates a persistent network connectivity issue, server unavailability, or infrastructure problem. Such problems prevent data retrieval. The library implements retry logic with exponential backoff and circuit breaker patterns before raising this exception. A NetworkError typically means the problem is serious and persistent. Signature:
Context Keys:
  • url (str | None): The full URL that failed (for example, “https://cdn.jsdelivr.net/gh/TracingInsights/2024@main/…”)
  • status_code (int | None): HTTP status code if the server responded (for example, 500, 502, 503, 504)
  • Additional context from **context kwargs (may include retry count, timeout info, etc.)
When Raised:
  • All retries exhausted (typically 3-5 retries with exponential backoff)
  • CDN fallback mechanisms failed
  • HTTP 5xx server errors (500, 502, 503, 504) persisting after retries
  • Connection timeouts exceeding configured thresholds
  • DNS resolution failures
  • SSL/TLS certificate validation errors
  • Network connectivity issues (no internet connection)
  • Firewall or proxy blocking requests
Common Scenarios:
  1. CDN Outage: One or more CDN sources (jsDelivr, Hugging Face buckets, StaticDelivr) experiencing downtime or degraded performance
  2. GitHub Issues: Source repository unavailable or rate-limited
  3. Local Network: No internet connection or restrictive firewall
  4. Server Errors: Backend infrastructure experiencing issues
  5. Timeout: Requests taking too long due to slow network or large files
HTTP Status Codes:
  • 500 Internal Server Error: CDN or origin server error
  • 502 Bad Gateway: CDN cannot reach origin server
  • 503 Service Unavailable: Server temporarily overloaded or down
  • 504 Gateway Timeout: CDN timeout waiting for origin server
  • None: Connection failed before receiving response (timeout, DNS failure, etc.)
Example - Basic Handling:
Example - Retry with Exponential Backoff:
Example - Fallback to Cached Data:
Example - Network Health Check:
Example - Timeout Configuration:
Example - Batch Loading with Error Tracking:
Example - Monitoring and Alerting:

Data Validation Errors

InvalidDataError

Raised when fetched data is invalid, corrupted, malformed, or fails validation checks. This exception indicates that the network request succeeded and data was retrieved. The data itself does not meet the format, schema, or quality standards required by the library. This is distinct from DataNotFoundError (data does not exist) and NetworkError (could not retrieve data). InvalidDataError means the data was retrieved but is unusable. Signature:
Context Keys:
  • reason (str | None): Detailed description of why the data is invalid
  • Additional context from **context kwargs (may include field names, expected vs actual values, etc.)
When Raised:
  • JSON parsing failures (malformed JSON syntax)
  • Missing required fields in data structures
  • Data type mismatches (string where number expected)
  • Invalid enum values (unknown session type, compound type, etc.)
  • Corrupted or truncated data files
  • Schema validation failures (pydantic validation errors)
  • Inconsistent data (lap times without lap numbers, etc.)
  • Data integrity violations (negative lap times, impossible speeds, etc.)
  • Encoding issues (invalid UTF-8, etc.)
Common Scenarios:
  1. Malformed JSON: CDN served corrupted or incomplete JSON
  2. Schema Changes: Data structure changed but library not updated
  3. Missing Fields: Required columns or fields absent from data
  4. Type Errors: Data types do not match expected schema
  5. Validation Failures: Data values outside acceptable ranges
  6. Encoding Issues: Character encoding problems in text fields
Example - Basic Handling:
Example - Detailed Error Inspection:
Example - Graceful Degradation:
Example - Validation Error Recovery:
Example - Data Quality Checks:
Example - Batch Validation:
Example - Custom Validation Rules:
Example - Error Reporting:

Cache Errors

CacheError

Raised when cache operations fail, typically due to SQLite database errors, filesystem issues, or resource constraints. The library uses an SQLite-backed cache to store fetched data locally, and this exception indicates problems with that caching layer. Cache errors are generally non-fatal for data retrieval. The library can fall back to fetching from CDN. Cache errors may impact performance and offline capabilities. Signature:
Context Keys:
  • Additional context from **context kwargs (may include cache path, operation type, SQLite error codes, etc.)
When Raised:
  • SQLite database corruption or lock errors
  • Insufficient disk space for cache operations
  • Permission denied when accessing cache directory
  • Cache database schema migration failures
  • Concurrent access conflicts (multiple processes)
  • Filesystem errors (read-only filesystem, etc.)
  • Cache directory does not exist and cannot be created
  • Database connection failures
  • Transaction rollback errors
Common Scenarios:
  1. Disk Full: No space left on device for cache writes
  2. Permissions: Cache directory not writable by current user
  3. Corruption: SQLite database file corrupted
  4. Locks: Database locked by another process
  5. Migration: Cache schema version mismatch
Example - Basic Handling:
Example - Cache Operations with Fallback:
Example - Cache Diagnostics:
Example - Cache Repair:
Example - Cache Monitoring:
Example - Graceful Cache Degradation:
Example - Cache Configuration:

Session State Errors

SessionNotLoadedError

Raised when attempting to access session data or attributes before the session has been properly loaded. This exception enforces the library’s data loading contract, ensuring that users explicitly load data before accessing it. The library uses lazy loading patterns for performance, meaning session objects can be created without immediately fetching all data. This exception occurs on access to data that requires an explicit load operation. Signature:
Context Keys:
  • attribute (str | None): The specific attribute or property that was accessed before loading
When Raised:
  • Accessing session.laps before calling session.load(laps=True)
  • Accessing session.telemetry before loading telemetry data
  • Accessing driver-specific data before session initialization completes
  • Calling methods that require loaded data on an unloaded session
  • Accessing internal data structures (for example, _laps_df) before population
Common Scenarios:
  1. Forgot to Load: Created session but did not call load methods
  2. Partial Loading: Loaded some data but not the specific data needed
  3. Lazy Loading: Accessing properties that trigger lazy loading failures
  4. Internal Access: Directly accessing private attributes before initialization
Example - Basic Handling:
Example - Proper Loading Pattern:
Example - Checking Load Status:
Example - Lazy Loading Wrapper:
Example - Selective Loading:
Example - Batch Loading with Error Handling:
Example - Progressive Loading:
Example - Load Status Checker:

Error Handling Patterns

This section provides patterns for handling tif1 exceptions in real-world applications. These patterns demonstrate best practices for reliability, maintainability, and user experience.

Basic Try-Catch Pattern

The fundamental pattern for handling tif1 exceptions. Always catch specific exceptions before general ones to enable targeted error handling.

Specific Error Handling Pattern

Handle specific errors with targeted recovery strategies.

Retry with Exponential Backoff Pattern

Implement retry logic for transient network errors.

Circuit Breaker Pattern

Implement circuit breaker to prevent cascading failures.

Fallback Chain Pattern

Implement multiple fallback strategies in sequence.

Context-Aware Error Handling Pattern

Extract and use structured context for error handling.

Best Practices

Guidelines for reliable error handling in production applications using tif1.

1. Catch Specific Exceptions First

Always catch more specific exceptions before general ones. Python evaluates except clauses in order, so place specific handlers first. Why: Specific exceptions allow targeted recovery strategies and better error messages.

2. Always Use Context Information

Every tif1 exception includes a context dictionary with structured metadata. Use this for debugging, logging, and error recovery. Why: Context provides actionable information for debugging and monitoring.

3. Never Swallow Errors Silently

Always log errors or provide user feedback. Silent failures make debugging impossible. Why: Silent failures hide problems and make debugging difficult.

4. Implement Retries for Network Errors

Network errors are often transient. Implement retry logic with exponential backoff. Why: Temporary network issues should not cause permanent failures.

5. Validate User Input Early

Check user input before making expensive API calls or network requests. Why: Fail fast with clear error messages rather than cryptic exceptions later.

6. Use Try-Finally for Resource Cleanup

Ensure resources are cleaned up even when errors occur. Why: Prevents resource leaks and ensures consistent state.

7. Log Context for Debugging

The context dictionary contains valuable debugging information. Always log it. Why: Structured context enables effective debugging and monitoring.

8. Provide User-Friendly Error Messages

Translate technical errors into actionable user messages. Why: Users need clear guidance, not technical jargon.

9. Implement Graceful Degradation

When possible, provide partial functionality rather than complete failure. Why: Better user experience and more resilient applications.

10. Use Type Hints and Documentation

Document exception behavior in docstrings and use type hints. Why: Clear documentation prevents misuse and aids maintenance.

11. Monitor and Alert on Errors

Implement monitoring for production applications. Why: Proactive error detection prevents user impact.

12. Test Error Handling

Write tests for error scenarios. Why: Ensures error handling works correctly.

Summary Checklist

When handling tif1 exceptions:
  • ✓ Catch specific exceptions before general ones
  • ✓ Use and log the context dictionary
  • ✓ Never swallow errors silently
  • ✓ Implement retries for network errors
  • ✓ Validate user input early
  • ✓ Use try-finally for cleanup
  • ✓ Log structured context for debugging
  • ✓ Provide user-friendly error messages
  • ✓ Implement graceful degradation where possible
  • ✓ Document exception behavior
  • ✓ Monitor errors in production
  • ✓ Test error handling code
Last modified on September 8, 2026