Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/TracingInsights/tif1/llms.txt

Use this file to discover all available pages before exploring further.

The tif1.exceptions module defines a comprehensive exception hierarchy for error handling throughout the library. All exceptions inherit from the base TIF1Error class and support structured context information.

Exception Hierarchy

TIF1Error
├── DataNotFoundError
│   ├── DriverNotFoundError
│   └── LapNotFoundError
├── NetworkError
├── InvalidDataError
├── CacheError
└── SessionNotLoadedError

Base Exception

TIF1Error

class TIF1Error(Exception):
    """Base exception for tif1."""
    
    def __init__(self, message: str, **context: Any) -> None:
        ...
Base exception class for all tif1 errors. Stores both a message and arbitrary context information for debugging. Attributes:
  • message: str - Human-readable error message
  • context: dict[str, Any] - Additional context information passed as kwargs
When Raised: Not raised directly; serves as base class for all other tif1 exceptions. Example:
try:
    session.load()
except TIF1Error as e:
    print(f"Error: {e.message}")
    print(f"Context: {e.context}")

Data Errors

DataNotFoundError

class DataNotFoundError(TIF1Error):
    """Raised when requested data is not available."""
    
    def __init__(
        self,
        year: int | None = None,
        event: str | None = None,
        session: str | None = None,
        **context: Any,
    ) -> None:
        ...
Raised when requested F1 data is not available from the data source. Parameters:
  • year: int | None - Year of the event
  • event: str | None - Event name or identifier
  • session: str | None - Session type
  • **context - Additional context information
Context Attributes:
  • Stores year, event, session in context dict
  • Plus any additional kwargs passed
When Raised:
  • Session data not available for the specified year/event/session combination
  • Event not found in the schedule
  • Session type not available for the event
  • Data source returns 404 or indicates data doesn’t exist
Example:
import tif1
from tif1.exceptions import DataNotFoundError

try:
    session = tif1.get_session(2030, "NonExistent", "Race")
    session.load()
except DataNotFoundError as e:
    print(f"Could not find data: {e.message}")
    print(f"Year: {e.context.get('year')}")
    print(f"Event: {e.context.get('event')}")

DriverNotFoundError

class DriverNotFoundError(DataNotFoundError):
    """Raised when driver is not found in session."""
    
    def __init__(self, driver: str, **context: Any) -> None:
        ...
Raised when attempting to access a driver that doesn’t exist in the session. Parameters:
  • driver: str - Driver identifier that was not found
  • **context - Additional context information
Context Attributes:
  • driver - The driver identifier that was searched for
  • Plus any additional kwargs passed
When Raised:
  • Calling session.get_driver() with an invalid driver code
  • Accessing session.laps.pick_driver() with non-existent driver
  • Driver not participating in the session
  • Invalid driver number or 3-letter code
Example:
import tif1
from tif1.exceptions import DriverNotFoundError

session = tif1.get_session(2024, "Monaco", "Race")
session.load()

try:
    driver = session.get_driver("XXX")  # Invalid driver code
except DriverNotFoundError as e:
    print(f"Error: {e.message}")
    print(f"Driver: {e.context['driver']}")

LapNotFoundError

class LapNotFoundError(DataNotFoundError):
    """Raised when lap is not found."""
    
    def __init__(
        self,
        lap_number: int | None = None,
        driver: str | None = None,
        **context: Any,
    ) -> None:
        ...
Raised when attempting to access a lap that doesn’t exist. Parameters:
  • lap_number: int | None - Lap number that was not found
  • driver: str | None - Driver for whom the lap was searched
  • **context - Additional context information
Context Attributes:
  • lap_number - The lap number searched for
  • driver - The driver identifier
  • Plus any additional kwargs passed
When Raised:
  • Requesting a lap number that doesn’t exist for a driver
  • Accessing out-of-range lap indices
  • Driver didn’t complete the requested lap (DNF, DNS)
  • Lap data not available or was deleted
Example:
import tif1
from tif1.exceptions import LapNotFoundError

session = tif1.get_session(2024, "Monaco", "Race")
session.load()

try:
    lap = session.laps.pick_driver("VER").pick_lap(999)  # Non-existent lap
except LapNotFoundError as e:
    print(f"Error: {e.message}")
    print(f"Lap: {e.context.get('lap_number')}")
    print(f"Driver: {e.context.get('driver')}")

Network Errors

NetworkError

class NetworkError(TIF1Error):
    """Raised when network request fails."""
    
    def __init__(
        self,
        url: str | None = None,
        status_code: int | None = None,
        **context: Any,
    ) -> None:
        ...
Raised when HTTP requests to data sources fail. Parameters:
  • url: str | None - URL that failed
  • status_code: int | None - HTTP status code received
  • **context - Additional context information
Context Attributes:
  • url - The URL that was requested
  • status_code - HTTP status code (e.g., 500, 503)
  • Plus any additional kwargs passed
When Raised:
  • HTTP request timeout
  • Server returns 5xx error
  • Connection failure
  • CDN unavailable
  • Network connectivity issues
  • Rate limiting (429)
  • Circuit breaker open after repeated failures
Example:
import tif1
from tif1.exceptions import NetworkError

try:
    session = tif1.get_session(2024, "Monaco", "Race")
    session.load()
except NetworkError as e:
    print(f"Network error: {e.message}")
    print(f"URL: {e.context.get('url')}")
    print(f"Status: {e.context.get('status_code')}")

Data Validation Errors

InvalidDataError

class InvalidDataError(TIF1Error):
    """Raised when fetched data is invalid or corrupted."""
    
    def __init__(self, reason: str | None = None, **context: Any) -> None:
        ...
Raised when data from sources is malformed, corrupted, or doesn’t match expected schema. Parameters:
  • reason: str | None - Description of what is invalid
  • **context - Additional context information
Context Attributes:
  • reason - Why the data is invalid
  • Plus any additional kwargs passed
When Raised:
  • JSON parsing fails
  • Data doesn’t match expected schema
  • Required fields missing from response
  • Data type mismatches
  • Corrupted cache entries
  • Invalid data format
Example:
import tif1
from tif1.exceptions import InvalidDataError

try:
    session = tif1.get_session(2024, "Monaco", "Race")
    session.load()
except InvalidDataError as e:
    print(f"Invalid data: {e.message}")
    print(f"Reason: {e.context.get('reason')}")

Cache Errors

CacheError

class CacheError(TIF1Error):
    """Raised when cache operations fail."""
Raised when SQLite cache operations encounter errors. When Raised:
  • Cannot create cache directory
  • SQLite database corruption
  • Insufficient disk space for cache
  • Cache database locked
  • Permission errors on cache files
  • Cache write failures
Example:
import tif1
from tif1.exceptions import CacheError

try:
    session = tif1.get_session(2024, "Monaco", "Race")
    session.load()
except CacheError as e:
    print(f"Cache error: {e.message}")
    print(f"Context: {e.context}")

Session State Errors

SessionNotLoadedError

class SessionNotLoadedError(TIF1Error):
    """Raised when accessing session data before loading."""
    
    def __init__(self, attribute: str | None = None) -> None:
        ...
Raised when attempting to access session data before calling session.load(). Parameters:
  • attribute: str | None - The attribute that was accessed
Context Attributes:
  • attribute - Name of the attribute that requires loading
When Raised:
  • Accessing session.laps before load()
  • Accessing session.results before load()
  • Accessing session.weather before load(laps=True, weather=True)
  • Accessing any data property that requires loaded data
Example:
import tif1
from tif1.exceptions import SessionNotLoadedError

session = tif1.get_session(2024, "Monaco", "Race")

try:
    laps = session.laps  # Accessing before load()
except SessionNotLoadedError as e:
    print(f"Error: {e.message}")
    print(f"Attribute: {e.context.get('attribute')}")
    # Solution: call session.load() first
    session.load()
    laps = session.laps  # Now works

Error Handling Best Practices

Catch Specific Exceptions

import tif1
from tif1.exceptions import (
    DataNotFoundError,
    NetworkError,
    SessionNotLoadedError,
    TIF1Error,
)

def load_session_safely(year: int, event: str, session_type: str):
    try:
        session = tif1.get_session(year, event, session_type)
        session.load()
        return session
    except SessionNotLoadedError:
        print("Session not loaded - this shouldn't happen here")
    except DataNotFoundError as e:
        print(f"Data not available: {e.context}")
        return None
    except NetworkError as e:
        print(f"Network issue, retry later: {e.context.get('status_code')}")
        return None
    except TIF1Error as e:
        print(f"Other tif1 error: {e.message}")
        return None

Access Error Context

from tif1.exceptions import DriverNotFoundError

try:
    driver = session.get_driver("XXX")
except DriverNotFoundError as e:
    # Access structured context
    driver_code = e.context["driver"]
    print(f"Driver '{driver_code}' not found")
    
    # Available drivers for suggestion
    available = [d.abbreviation for d in session.drivers]
    print(f"Available drivers: {', '.join(available)}")

Retry on Network Errors

import time
from tif1.exceptions import NetworkError

def load_with_retry(session, max_retries=3):
    for attempt in range(max_retries):
        try:
            session.load()
            return True
        except NetworkError as e:
            if attempt < max_retries - 1:
                wait_time = 2 ** attempt  # Exponential backoff
                print(f"Retry {attempt + 1}/{max_retries} after {wait_time}s")
                time.sleep(wait_time)
            else:
                print(f"Failed after {max_retries} attempts: {e.message}")
                return False

Build docs developers (and LLMs) love