Error Handling Guide

Error Handling Guide

Overview

The godot-torrent library implements a standardized error handling system that provides:

Error System Components

1. TorrentError Class

The TorrentError class represents a single error with detailed information.

Key Properties:

Creating Errors:

# Create from error code
var error = TorrentError.create(TorrentError.INVALID_TORRENT_FILE, "Custom message", "context")

# Create from libtorrent error
var error = TorrentError.from_libtorrent_error(error_code, error_message, "context")

# Convert to dictionary
var error_dict = error.to_dict()
print(error_dict)  # { "code": 201, "category": "torrent", "message": "...", ... }

2. TorrentResult Class

The TorrentResult class is a wrapper for operations that can fail, similar to Rust’s Result<T, E> type.

Key Methods:

Usage Pattern:

# Methods that can fail return TorrentResult
var result = some_operation_that_can_fail()

if result.is_ok():
    var value = result.get_value()
    print("Success: ", value)
else:
    var error = result.get_error()
    print("Error: ", error.get_message())
    print("Category: ", error.get_category())
    print("Recoverable: ", error.is_recoverable())

Error Categories

Errors are organized into categories for easier handling:

Category Code Range Description
NONE 0 No error (success)
SESSION_ERROR 100-199 Session lifecycle and configuration errors
TORRENT_ERROR 200-299 Torrent-specific errors
NETWORK_ERROR 300-399 Network connectivity and timeout errors
STORAGE_ERROR 400-499 File system and storage errors
PARSE_ERROR 500-599 Data parsing and format errors
VALIDATION_ERROR 600-699 Input validation errors
TRACKER_ERROR 700-799 Tracker communication errors
DHT_ERROR 800-899 DHT-related errors
PEER_ERROR 900-999 Peer connection errors
INTERNAL_ERROR 1000+ Internal library errors

Common Error Codes

Session Errors (100-199)

Torrent Errors (200-299)

Storage Errors (400-499)

Validation Errors (600-699)

Error Handling Best Practices

1. Always Check for Errors

var session = TorrentSession.new()
var success = session.start_session()
if not success:
    # Handle error - check Godot console for detailed message
    print("Failed to start session")
    return

2. Check Return Values

Operations that can fail will log errors to the Godot console via push_error():

var handle = session.add_torrent_file(torrent_data, save_path)
if handle == null or not handle.is_valid():
    # Error occurred - check console for details
    print("Failed to add torrent")
    return

3. Validate Inputs

Always validate inputs before calling library methods:

# Bad - will cause error
var handle = session.add_torrent_file(data, "")  # Empty path

# Good - validate first
if save_path.is_empty():
    print("Error: Save path cannot be empty")
    return

var handle = session.add_torrent_file(data, save_path)

4. Check Session State

if not session.is_running():
    print("Session not running - start it first")
    session.start_session()

5. Validate Handle Before Use

if not handle.is_valid():
    print("Handle is invalid - cannot perform operation")
    return

handle.pause()  # Safe to use

Error Messages

All errors are reported to the Godot console using push_error() with a standardized format:

[ClassName::method_name] Error message

Examples:

[TorrentSession::add_torrent_file] Session not running
[TorrentSession::add_torrent_file] Save path cannot be empty
[TorrentSession::add_torrent_file] libtorrent error 123: invalid torrent file
[TorrentHandle::pause] Invalid handle
[TorrentHandle::set_piece_priority] Exception: out of range

Libtorrent Error Mapping

Libtorrent errors are automatically mapped to godot-torrent error codes:

Libtorrent Error Mapped Code Category
Invalid torrent file INVALID_TORRENT_FILE TORRENT_ERROR
Invalid magnet INVALID_MAGNET_URI TORRENT_ERROR
Permission denied PERMISSION_DENIED STORAGE_ERROR
Disk full DISK_FULL STORAGE_ERROR
Timeout TIMEOUT NETWORK_ERROR
Tracker error TRACKER_ANNOUNCE_FAILED TRACKER_ERROR
Connection failed CONNECTION_FAILED NETWORK_ERROR

Recovery Strategies

Recoverable Errors

These errors can typically be retried or worked around:

Strategy: Retry with backoff, try alternative trackers, or continue without that resource.

Non-Recoverable Errors

These errors require user intervention:

Strategy: Report error to user, log details, and request corrective action.

Example: Complete Error Handling

extends Node

var session: TorrentSession
var handle: TorrentHandle

func _ready():
    session = TorrentSession.new()

    # Start session with error checking
    if not session.start_session():
        push_error("Failed to start torrent session")
        return

    # Load torrent file
    var file = FileAccess.open("res://test.torrent", FileAccess.READ)
    if file == null:
        push_error("Failed to open torrent file")
        session.stop_session()
        return

    var torrent_data = file.get_buffer(file.get_length())
    file.close()

    # Add torrent with validation
    var save_path = "downloads"
    if save_path.is_empty():
        push_error("Save path is empty")
        session.stop_session()
        return

    handle = session.add_torrent_file(torrent_data, save_path)
    if handle == null or not handle.is_valid():
        push_error("Failed to add torrent - check console for details")
        session.stop_session()
        return

    print("Torrent added successfully: ", handle.get_name())

func _exit_tree():
    if session != null:
        session.stop_session()

Future Enhancements

Planned improvements to the error handling system:

  1. Return TorrentResult from more methods - Gradually migrate from boolean/null returns to TorrentResult for better error information
  2. Error handling signals - Emit signals for errors to allow centralized error handling
  3. Error recovery helpers - Built-in retry logic and recovery strategies
  4. Structured error data - Additional structured data in errors for programmatic handling
  5. Error statistics - Track error frequency and patterns for debugging

Summary

The standardized error handling system provides:

Always check return values, validate inputs, and monitor the Godot console for detailed error information.