Error Handling
This guide shows you how to handle errors correctly when using the Retorna SDK.
Error Types
The SDK can throw different types of exceptions:
IllegalArgumentException
Thrown when the provided parameters are invalid:
try {
CreateOrderInput orderInput = new CreateOrderInput(
// ... invalid parameters
);
OrderResponse order = client.order.createPayoutOrder(orderInput);
} catch (IllegalArgumentException e) {
System.err.println("Validation error: " + e.getMessage());
// Example: "clientId is required"
}
RuntimeException
Thrown when there are API errors (4xx, 5xx) or network issues:
try {
BalanceResponse balance = client.account.getBalance();
} catch (RuntimeException e) {
System.err.println("API error: " + e.getMessage());
// Example: "Error fetching balance: 401 - Unauthorized"
}
Exception
Thrown for other general errors (parsing, connection, etc.):
try {
QuoteResponse quote = client.quotation.createQuote(quoteInput);
} catch (Exception e) {
System.err.println("General error: " + e.getMessage());
e.printStackTrace();
}
Recommended Error Handling
Basic Pattern
try {
// SDK operation
BalanceResponse balance = client.account.getBalance();
System.out.println("Balance: " + balance.getTotalBalance());
} catch (IllegalArgumentException e) {
// Validation error - invalid data
System.err.println("❌ Validation error: " + e.getMessage());
// Take corrective action (show message to user, etc.)
} catch (RuntimeException e) {
// API error - server issue
System.err.println("❌ API error: " + e.getMessage());
// Retry, notify, etc.
} catch (Exception e) {
// Unexpected error
System.err.println("❌ Unexpected error: " + e.getMessage());
e.printStackTrace();
// Logging, notification, etc.
}
Operation-Specific Handling
public class RetornaService {
public BalanceResponse getBalanceSafely(RetornaClient client) {
try {
return client.account.getBalance();
} catch (RuntimeException e) {
if (e.getMessage().contains("401") || e.getMessage().contains("403")) {
// Authentication error
throw new AuthenticationException("Invalid credentials", e);
} else if (e.getMessage().contains("500")) {
// Server error
throw new ServerException("Server error", e);
} else {
throw new RetornaException("Unknown error", e);
}
}
}
public OrderResponse createOrderSafely(RetornaClient client, CreateOrderInput input) {
try {
return client.order.createPayoutOrder(input);
} catch (IllegalArgumentException e) {
// Validation error
throw new ValidationException("Invalid data: " + e.getMessage(), e);
} catch (RuntimeException e) {
if (e.getMessage().contains("400")) {
// Bad Request
throw new BadRequestException("Invalid request", e);
} else {
throw new RetornaException("Error creating order", e);
}
}
}
}
HTTP Status Codes
The SDK can receive different HTTP status codes:
| Code | Meaning | Recommended Action |
|---|---|---|
| 200, 201 | Success | Continue normally |
| 400 | Bad Request | Verify parameters |
| 401 | Unauthorized | Verify credentials |
| 403 | Forbidden | Verify permissions |
| 404 | Not Found | Resource does not exist |
| 500 | Internal Server Error | Retry later |
| 503 | Service Unavailable | Service unavailable |
Status Code Handling Example
public class ErrorHandler {
public static void handleApiError(RuntimeException e) {
String message = e.getMessage();
if (message.contains("401")) {
System.err.println("❌ Authentication error. Verify your credentials.");
} else if (message.contains("403")) {
System.err.println("❌ Access denied. Verify your permissions.");
} else if (message.contains("404")) {
System.err.println("❌ Resource not found.");
} else if (message.contains("400")) {
System.err.println("❌ Invalid request. Verify parameters.");
} else if (message.contains("500") || message.contains("503")) {
System.err.println("❌ Server error. Try again later.");
} else {
System.err.println("❌ Unknown error: " + message);
}
}
}
Automatic Retries
The SDK automatically handles some retries:
- 401/403: The SDK attempts to renew the token and retry the request
- Network errors: You can implement your own retry logic
Implementing Manual Retries
import java.util.concurrent.TimeUnit;
public class RetryExample {
public static BalanceResponse getBalanceWithRetry(
RetornaClient client, int maxRetries) {
int attempts = 0;
while (attempts < maxRetries) {
try {
return client.account.getBalance();
} catch (RuntimeException e) {
attempts++;
if (e.getMessage().contains("500") || e.getMessage().contains("503")) {
// Server error - retry
if (attempts < maxRetries) {
System.out.println("Retrying... (" + attempts + "/" + maxRetries + ")");
try {
TimeUnit.SECONDS.sleep(2 * attempts); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted", ie);
}
continue;
}
}
// Other errors or retries exhausted
throw e;
}
}
throw new RuntimeException("Could not get balance after " + maxRetries + " attempts");
}
}
Error Logging
Use the SDK's logging system to debug errors:
RetornaClient client = RetornaClient.create(
RetornaClientOptions.builder()
.environment(Environment.DEVELOP)
.loggingLevel(LoggingLevel.DEBUG) // Enable detailed logging
// ... other configuration
.build()
);
With LoggingLevel.DEBUG, you will see:
- Authentication attempts
- HTTP requests
- API responses
- Detailed errors
Common Errors and Solutions
Error: "clientId is required"
Cause: ClientId was not provided when creating the client.
Solution:
.clientId("your-client-id") // Make sure to provide it
Error: "Error fetching balance: 401"
Cause: Invalid credentials or expired token.
Solution: Verify your credentials. The SDK will attempt to renew the token automatically.
Error: "Validation error: ..."
Cause: Invalid data in the request (e.g., incorrect document format).
Solution: Verify the data format according to the payout platform.
Error: "Unexpected response format"
Cause: The API returned an unexpected format.
Solution: Contact support or verify the SDK version.
Best Practices
- Always handle exceptions: Do not let exceptions propagate unhandled
- Provide context: Include useful information in error messages
- Appropriate logging: Use logging for debugging, not for production
- Smart retries: Only retry on recoverable errors (5xx)
- Early validation: Validate data before sending it to the SDK
Complete Example
public class RobustErrorHandling {
public static void processPayment(RetornaClient client, CreateOrderInput input) {
try {
// Validate input before sending
validateOrderInput(input);
// Create order
OrderResponse order = client.order.createPayoutOrder(input);
System.out.println("✅ Order created: " + order.getId());
} catch (IllegalArgumentException e) {
// Validation error
System.err.println("❌ Validation error: " + e.getMessage());
// Show message to user
showUserError("Please verify the entered data.");
} catch (RuntimeException e) {
// API error
if (e.getMessage().contains("401") || e.getMessage().contains("403")) {
System.err.println("❌ Authentication error");
// Re-authenticate or notify
} else if (e.getMessage().contains("400")) {
System.err.println("❌ Invalid request: " + e.getMessage());
// Show specific error
} else {
System.err.println("❌ API error: " + e.getMessage());
// Retry or notify
}
} catch (Exception e) {
// Unexpected error
System.err.println("❌ Unexpected error: " + e.getMessage());
e.printStackTrace();
// Logging and notification
}
}
private static void validateOrderInput(CreateOrderInput input) {
if (input.getExternalId() == null || input.getExternalId().isEmpty()) {
throw new IllegalArgumentException("externalId is required");
}
// More validations...
}
private static void showUserError(String message) {
// Implement UI or logging
System.out.println("Error: " + message);
}
}
Next Steps
- Advanced Topics - Advanced SDK features
- Examples - More usage examples



