Error Handling
The Samsara SDK provides a comprehensive exception hierarchy for handling API errors.
Exception Hierarchy
SamsaraException (base)
├── AuthenticationException (401)
├── AuthorizationException (403)
├── NotFoundException (404)
├── UnsupportedOperationException
├── ValidationException (422)
├── RateLimitException (429)
└── ServerException (5xx)
Catching Exceptions
Basic Error Handling
use Samsara\Facades\Samsara;
use Samsara\Exceptions\SamsaraException;
try {
$driver = Samsara::drivers()->find('driver-id');
} catch (SamsaraException $e) {
// Handle any API error
Log::error('Samsara API error: ' . $e->getMessage());
}
Specific Exception Handling
use Samsara\Facades\Samsara;
use Samsara\Exceptions\AuthenticationException;
use Samsara\Exceptions\AuthorizationException;
use Samsara\Exceptions\NotFoundException;
use Samsara\Exceptions\UnsupportedOperationException;
use Samsara\Exceptions\ValidationException;
use Samsara\Exceptions\RateLimitException;
use Samsara\Exceptions\ServerException;
use Samsara\Exceptions\SamsaraException;
try {
$driver = Samsara::drivers()->create($data);
} catch (AuthenticationException $e) {
// Invalid or expired API token (401)
Log::error('Invalid API token');
} catch (AuthorizationException $e) {
// Insufficient permissions (403)
Log::error('Permission denied');
} catch (NotFoundException $e) {
// Resource not found (404)
Log::warning('Resource not found');
} catch (UnsupportedOperationException $e) {
// Operation not supported (e.g., vehicle creation/deletion)
Log::warning('Unsupported operation: ' . $e->getMessage());
} catch (ValidationException $e) {
// Invalid request data (422)
$errors = $e->getErrors();
Log::warning('Validation failed', ['errors' => $errors]);
} catch (RateLimitException $e) {
// Too many requests (429)
$retryAfter = $e->getRetryAfter();
Log::warning("Rate limited. Retry after {$retryAfter} seconds");
} catch (ServerException $e) {
// Server error (5xx)
Log::error('Samsara server error: ' . $e->getMessage());
} catch (SamsaraException $e) {
// Other API errors
Log::error('API error: ' . $e->getMessage());
}
Exception Details
AuthenticationException (401)
Thrown when the API token is invalid or expired.
try {
$drivers = Samsara::drivers()->all();
} catch (AuthenticationException $e) {
// Check your SAMSARA_API_KEY in .env
echo $e->getMessage(); // "Invalid API token"
}
AuthorizationException (403)
Thrown when the authenticated user lacks permission.
try {
$driver = Samsara::drivers()->delete('driver-id');
} catch (AuthorizationException $e) {
echo $e->getMessage(); // "You don't have permission..."
}
NotFoundException (404)
Thrown when a requested resource doesn’t exist.
try {
$driver = Samsara::drivers()->find('invalid-id');
} catch (NotFoundException $e) {
// Note: find() returns null for 404, doesn't throw
}
// For other methods that throw on 404:
try {
$driver = Samsara::drivers()->delete('invalid-id');
} catch (NotFoundException $e) {
echo $e->getMessage(); // "Driver not found"
}
UnsupportedOperationException
Thrown when a resource does not support the requested operation. Some Samsara API resources have restrictions that prevent certain CRUD operations. For example, vehicles cannot be created or deleted via the /fleet/vehicles endpoint.
use Samsara\Facades\Samsara;
use Samsara\Exceptions\UnsupportedOperationException;
try {
Samsara::vehicles()->create(['name' => 'Truck 001']);
} catch (UnsupportedOperationException $e) {
// The exception message includes guidance on the correct approach
echo $e->getMessage();
// "Vehicles cannot be created via /fleet/vehicles. Vehicles are automatically
// created when a Samsara Vehicle Gateway is installed. To manually create
// vehicles, use the Assets API: $samsara->assets()->create(['type' => 'vehicle', ...])."
}
Unlike other exceptions in the hierarchy, this is not tied to an HTTP status code. It is thrown before any API request is made, indicating that the operation is fundamentally unsupported for the resource.
ValidationException (422)
Thrown when request data fails validation.
try {
$driver = Samsara::drivers()->create([
// Missing required fields
]);
} catch (ValidationException $e) {
// Get validation errors
$errors = $e->getErrors();
// [
// 'name' => ['Name is required'],
// 'phone' => ['Invalid phone format'],
// ]
foreach ($errors as $field => $messages) {
echo "{$field}: " . implode(', ', $messages);
}
}
RateLimitException (429)
Thrown when you exceed the API rate limit.
try {
$drivers = Samsara::drivers()->all();
} catch (RateLimitException $e) {
// Get retry-after value (seconds)
$retryAfter = $e->getRetryAfter();
if ($retryAfter) {
sleep($retryAfter);
// Retry the request
}
}
ServerException (5xx)
Thrown for server-side errors.
try {
$drivers = Samsara::drivers()->all();
} catch (ServerException $e) {
// Log and alert, likely a temporary issue
Log::critical('Samsara API is down', [
'message' => $e->getMessage(),
'code' => $e->getCode(),
]);
}
Exception Context
All exceptions include context information:
try {
$driver = Samsara::drivers()->find('driver-id');
} catch (SamsaraException $e) {
$context = $e->getContext();
// [
// 'status' => 404,
// 'endpoint' => '/fleet/drivers',
// 'body' => [...],
// ]
}
Retry Logic
The SDK includes automatic retry for transient failures. Configure in config/samsara.php:
'retry' => 3, // Number of retries
For manual retry with exponential backoff:
use Samsara\Facades\Samsara;
use Samsara\Exceptions\RateLimitException;
use Samsara\Exceptions\ServerException;
function fetchWithRetry(callable $callback, int $maxAttempts = 3): mixed
{
$attempt = 0;
while ($attempt < $maxAttempts) {
try {
return $callback();
} catch (RateLimitException $e) {
$retryAfter = $e->getRetryAfter() ?? pow(2, $attempt);
sleep($retryAfter);
$attempt++;
} catch (ServerException $e) {
sleep(pow(2, $attempt));
$attempt++;
}
}
throw new \RuntimeException('Max retry attempts exceeded');
}
// Usage
$drivers = fetchWithRetry(fn() => Samsara::drivers()->all());
Laravel Exception Handler
Handle Samsara exceptions globally in app/Exceptions/Handler.php:
use Samsara\Exceptions\SamsaraException;
use Samsara\Exceptions\AuthenticationException;
use Samsara\Exceptions\RateLimitException;
public function register(): void
{
$this->renderable(function (AuthenticationException $e) {
return response()->json([
'error' => 'Fleet API authentication failed',
], 500);
});
$this->renderable(function (RateLimitException $e) {
return response()->json([
'error' => 'Fleet API rate limit exceeded',
'retry_after' => $e->getRetryAfter(),
], 503);
});
$this->renderable(function (SamsaraException $e) {
Log::error('Samsara API error', [
'message' => $e->getMessage(),
'context' => $e->getContext(),
]);
return response()->json([
'error' => 'Fleet API error',
], 500);
});
}
Connection Errors
Network issues throw Laravel’s ConnectionException:
use Illuminate\Http\Client\ConnectionException;
use Samsara\Facades\Samsara;
try {
$drivers = Samsara::drivers()->all();
} catch (ConnectionException $e) {
// Network timeout, DNS failure, etc.
Log::error('Cannot connect to Samsara API: ' . $e->getMessage());
}