Skip to content

Error Handling

TQrouting raises its own exception hierarchy for everything related to your problem, license, or the solver — all of it inherits from TQRoutingError, so you can catch broadly or narrowly.

Plain argument misuse follows the standard Python convention instead: passing an invalid value to solve() (a negative time_limit, a negative objective weight, an unknown soft_constraints name) raises a built-in ValueError; an unknown keyword, or a value of the wrong type (a string for time_limit, a bool for nb_threads), raises a TypeError. These are programming errors — fix the call site rather than catching them at runtime; an except TQRoutingError handler does not catch them.

Exception Hierarchy

TQRoutingError (base)
├── ValidationError
├── SolverError
├── LicenseError
├── UnsupportedPlatformError
└── MatrixError
    ├── OSRMError
    ├── GoogleMapsError
    └── OSRMLocalManagerError

Catching Errors

import tqrouting

router = tqrouting.TQRouter()

try:
    solution = router.solve(problem)
except tqrouting.LicenseError as e:
    print(f"License problem: {e}")
except tqrouting.ValidationError as e:
    print(f"Invalid input: {e}")
except tqrouting.SolverError as e:
    print(f"Solver failed: {e}")
    print(f"Details: {e.details}")
except tqrouting.TQRoutingError as e:
    print(f"Unexpected error: {e}")

A ValueError/TypeError escaping this block means the call itself is wrong (bad argument value or name) — correct the code instead of widening the handler.


Exception Reference

TQRoutingError

Base class for all TQrouting exceptions. Catch this to handle any library error:

try:
    solution = router.solve(problem)
except tqrouting.TQRoutingError as e:
    print(f"Something went wrong: {e}")

LicenseError

Raised when the license key is missing, invalid, or expired.

Attributes:

Attribute Type Description
expiry_date str or None The expiration date (if the key is expired)
try:
    solution = router.solve(problem)
except tqrouting.LicenseError as e:
    if e.expiry_date:
        print(f"License expired on {e.expiry_date}")
    else:
        print(f"License error: {e}")

Common causes:

  • No license key provided (and TQROUTING_LICENSE_KEY env var not set)
  • Key has expired
  • Key signature is invalid

UnsupportedPlatformError

Raised on the first solve() when no solver engine is bundled for the current OS/architecture. Supported platforms: linux/amd64, macos/arm64 (Apple Silicon), windows/amd64 — notably, Intel Macs are not supported.

try:
    solution = router.solve(problem)
except tqrouting.UnsupportedPlatformError as e:
    print(e)   # names your platform and lists the supported ones

ValidationError

Raised when input data fails validation (before solving) or output data fails validation (after solving).

try:
    solution = router.solve(problem)
except tqrouting.ValidationError as e:
    print(f"Validation failed: {e}")

Common causes:

  • No matrix provided (need at least distance_matrix or duration_matrix)
  • Matrix has more rows than max(matrix_id) + 1, or the two matrices differ in size, or two customers share a matrix_id
  • Time window start > end, or a negative time window
  • A negative or malformed max_duration, max_distance, shift_start or shift_end (e.g. -1, "abc")
  • A time string that is not HH:MM:SS (such as "08:00"), or time fields in two formats within one instance (some HH:MM:SS strings, some numbers)
  • Single customer load exceeds max vehicle capacity (in either dimension, on 2-D instances)
  • A vehicle type without a capacity its customers demand, on an instance where both quantities appear (in demands or in capacities)
  • Fleet has no vehicle types
  • A custom id on only some customers (or only some vehicle types), or the same id twice within one of the two lists
  • A profit on only some customers (prize-collecting covers the whole instance)
  • x/y coordinates on only some locations

SolverError

Raised when the solver fails unexpectedly — an internal error, a crash, or running out of memory. Valid input should never trigger it: if you see one, it is most likely a bug in tqrouting. Please report it and attach e.details, which carries the full diagnostic payload for us to debug.

try:
    solution = router.solve(problem)
except tqrouting.SolverError as e:
    print(e)          # human-readable summary
    print(e.details)  # diagnostic payload to attach to a bug report

MatrixError

Base class for errors from distance matrix providers.


OSRMError

Raised when the OSRM service returns an error or is unreachable.

from tqrouting.matrix import OSRMMatrixProvider

provider = OSRMMatrixProvider(base_url="https://router.project-osrm.org")
try:
    instance.compute_distance_matrix(provider)
except tqrouting.OSRMError as e:
    print(f"OSRM error: {e}")

Common causes:

  • OSRM server not running
  • Network timeout
  • Coordinates outside the loaded map region

GoogleMapsError

Raised when the Google Routes API returns an error.

from tqrouting.matrix import GoogleMatrixProvider

provider = GoogleMatrixProvider()
try:
    instance.compute_distance_matrix(provider)
except tqrouting.GoogleMapsError as e:
    print(f"Google Maps error: {e}")

Common causes:

  • Invalid or expired API key
  • Quota exceeded
  • No route found between coordinates

OSRMLocalManagerError

Raised when the local OSRM Docker management fails.

from tqrouting.matrix import OSRMLocalManager

try:
    with OSRMLocalManager(region="europe/germany/bayern") as provider:
        instance.compute_distance_matrix(provider)
except tqrouting.OSRMLocalManagerError as e:
    print(f"OSRM local error: {e}")

Common causes:

  • Docker is not running
  • Map download failed (network error)
  • Preprocessing step failed (disk space, permissions)
  • Container failed to start
  • Health check timeout

Warnings

Some situations are legal but almost always unintended. The SDK emits a UserWarning instead of failing, so the solve still runs:

Warning Trigger Fix
No feasible solution The result violates constraints (solution_status == "Infeasible") Relax constraints, mark some as soft, or raise time_limit
All customers skipped Prize-collecting instance where every prize is below its travel cost Raise profits or profit_weight — prizes are in objective units
Times measured on distances Time-based fields (time_window, service_time, shift_*, max_duration) on an instance without a duration_matrix Provide a duration_matrix
Distance weight without distance matrix distance_weight > 0 but no separate distance_matrix Provide a distance_matrix for a real duration/distance trade-off
Vehicle without capacity On an instance with a single quantity, customers carry delivery_load / pickup_load (or volume) but a vehicle type has no capacity_load (capacity_volume), so its vehicles carry unlimited load Set the capacity, or silence the warning if that vehicle type is meant to be unlimited
Inert parameter penalty_waiting without time windows, profit_weight without profits, or a soft_constraints entry with nothing to soften Remove the parameter, or add the data it acts on

Silence any of them with Python's standard tools once reviewed:

import warnings

with warnings.catch_warnings():
    warnings.simplefilter("ignore", UserWarning)
    solution = router.solve(problem)