Overview
The MT5 Manager API SDK uses the ApiException class to handle all API-related errors. This exception provides detailed information about HTTP status codes, response headers, and response bodies.
ApiException Class
The ApiException class extends PHP’s standard Exception and provides additional context about API errors:
namespace D4T\MT5Sdk;
use \Exception;
class ApiException extends Exception
{
protected $responseBody; // HTTP response body
protected $responseHeaders; // HTTP response headers
protected $responseObject; // Deserialized response object
}
Basic Error Handling
Catching API Exceptions
use D4T\MT5Sdk\MT5Manager\BasicApi;
use D4T\MT5Sdk\ApiException;
$api = new BasicApi();
try {
$result = $api->initGet('127.0.0.1:443', 'manager_login', 'wrong_password');
} catch (ApiException $e) {
echo "API Error occurred:\n";
echo "Message: " . $e->getMessage() . "\n";
echo "HTTP Code: " . $e->getCode() . "\n";
}
Exception Properties
The ApiException constructor accepts four parameters:
public function __construct(
$message = "", // Error message
$code = 0, // HTTP status code
$responseHeaders = [], // HTTP response headers
$responseBody = null // HTTP response body
)
Human-readable error message
HTTP status code (e.g., 400, 401, 500)
Array of HTTP response headers
HTTP response body as string or object
Accessing Error Details
Response Body
Get the raw response body from the API:
try {
$result = $api->someMethod();
} catch (ApiException $e) {
$responseBody = $e->getResponseBody();
// Response body might be JSON string or object
if (is_string($responseBody)) {
$errorData = json_decode($responseBody, true);
echo "Error details: " . print_r($errorData, true);
}
}
Access HTTP response headers:
try {
$result = $api->someMethod();
} catch (ApiException $e) {
$headers = $e->getResponseHeaders();
if (isset($headers['Content-Type'])) {
echo "Response type: " . $headers['Content-Type'][0] . "\n";
}
}
Response Object
Get the deserialized response object:
try {
$result = $api->pingGet();
} catch (ApiException $e) {
$responseObject = $e->getResponseObject();
if ($responseObject !== null) {
// Object was successfully deserialized despite error
echo "Structured error: " . print_r($responseObject, true);
}
}
Common Error Scenarios
Authentication Errors
use D4T\MT5Sdk\MT5Manager\BasicApi;
use D4T\MT5Sdk\ApiException;
$api = new BasicApi();
try {
$result = $api->initGet('127.0.0.1:443', 'invalid_login', 'invalid_password');
} catch (ApiException $e) {
if ($e->getCode() === 401) {
echo "Authentication failed. Please check your credentials.\n";
} elseif ($e->getCode() === 403) {
echo "Access forbidden. Insufficient permissions.\n";
} else {
echo "Authentication error: " . $e->getMessage() . "\n";
}
}
Always handle authentication errors gracefully and avoid exposing sensitive error details to end users.
Connection Errors
try {
$result = $api->initGet('invalid-host:443', 'login', 'password');
} catch (ApiException $e) {
if ($e->getCode() === 0) {
echo "Network error: Could not connect to server\n";
echo "Details: " . $e->getMessage() . "\n";
}
}
Validation Errors
try {
// Missing required parameter
$result = $api->initGet(null, 'login', 'password');
} catch (\InvalidArgumentException $e) {
echo "Validation error: " . $e->getMessage() . "\n";
// Output: "Missing the required parameter $server when calling initGet"
} catch (ApiException $e) {
echo "API error: " . $e->getMessage() . "\n";
}
The SDK throws InvalidArgumentException for missing required parameters before making API requests.
HTTP Status Code Errors
try {
$result = $api->someMethod();
} catch (ApiException $e) {
switch ($e->getCode()) {
case 400:
echo "Bad Request: Invalid parameters\n";
break;
case 401:
echo "Unauthorized: Invalid or missing token\n";
break;
case 403:
echo "Forbidden: Insufficient permissions\n";
break;
case 404:
echo "Not Found: Resource does not exist\n";
break;
case 429:
echo "Too Many Requests: Rate limit exceeded\n";
break;
case 500:
echo "Internal Server Error\n";
break;
case 503:
echo "Service Unavailable: Server is down\n";
break;
default:
echo "Error " . $e->getCode() . ": " . $e->getMessage() . "\n";
}
}
Advanced Error Handling
function handleApiError(ApiException $e) {
$errorInfo = [
'message' => $e->getMessage(),
'code' => $e->getCode(),
'headers' => $e->getResponseHeaders(),
'body' => $e->getResponseBody(),
'object' => $e->getResponseObject()
];
// Log error
error_log(json_encode($errorInfo));
// Display user-friendly message
switch ($e->getCode()) {
case 401:
return "Please log in again. Your session has expired.";
case 500:
return "Server error. Please try again later.";
default:
return "An error occurred. Please contact support.";
}
}
try {
$result = $api->someMethod();
} catch (ApiException $e) {
$message = handleApiError($e);
echo $message;
}
Retry Logic
function callApiWithRetry($callable, $maxRetries = 3) {
$attempt = 0;
while ($attempt < $maxRetries) {
try {
return $callable();
} catch (ApiException $e) {
$attempt++;
// Retry on server errors or rate limits
if (in_array($e->getCode(), [429, 500, 503]) && $attempt < $maxRetries) {
$delay = pow(2, $attempt); // Exponential backoff
echo "Retry attempt $attempt after {$delay}s...\n";
sleep($delay);
continue;
}
// Don't retry on client errors
throw $e;
}
}
}
// Usage
try {
$result = callApiWithRetry(function() use ($api) {
return $api->pingGet();
});
} catch (ApiException $e) {
echo "Failed after retries: " . $e->getMessage() . "\n";
}
Custom Exception Handler
class MT5ExceptionHandler {
public static function handle(\Throwable $e) {
if ($e instanceof ApiException) {
self::handleApiException($e);
} elseif ($e instanceof \InvalidArgumentException) {
self::handleValidationException($e);
} else {
self::handleGenericException($e);
}
}
private static function handleApiException(ApiException $e) {
$logData = [
'type' => 'API_ERROR',
'code' => $e->getCode(),
'message' => $e->getMessage(),
'body' => $e->getResponseBody()
];
error_log(json_encode($logData));
}
private static function handleValidationException(\InvalidArgumentException $e) {
error_log("Validation Error: " . $e->getMessage());
}
private static function handleGenericException(\Throwable $e) {
error_log("Unexpected Error: " . $e->getMessage());
}
}
// Usage
try {
$result = $api->initGet('127.0.0.1:443', 'login', 'password');
} catch (\Throwable $e) {
MT5ExceptionHandler::handle($e);
}
Error Response Structure
Typical error response from the API:
{
"error": {
"code": "INVALID_CREDENTIALS",
"message": "Authentication failed",
"details": {
"reason": "Invalid password"
}
}
}
Parsing error responses:
try {
$result = $api->someMethod();
} catch (ApiException $e) {
$body = $e->getResponseBody();
if (is_string($body)) {
$error = json_decode($body, true);
if (isset($error['error'])) {
echo "Error Code: " . $error['error']['code'] . "\n";
echo "Message: " . $error['error']['message'] . "\n";
if (isset($error['error']['details'])) {
echo "Details: " . print_r($error['error']['details'], true);
}
}
}
}
Best Practices
- Always wrap API calls in try-catch blocks - Never make API calls without error handling
- Log detailed error information - Include response body and headers in logs for debugging
- Show user-friendly messages - Don’t expose raw API errors to end users
- Implement retry logic - Retry on transient errors (429, 500, 503)
- Handle validation errors - Catch
InvalidArgumentException for parameter validation
- Monitor error rates - Track and alert on high error rates in production
Next Steps