Skip to main content

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();
}

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:

CodeMeaningRecommended Action
200, 201SuccessContinue normally
400Bad RequestVerify parameters
401UnauthorizedVerify credentials
403ForbiddenVerify permissions
404Not FoundResource does not exist
500Internal Server ErrorRetry later
503Service UnavailableService 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

  1. Always handle exceptions: Do not let exceptions propagate unhandled
  2. Provide context: Include useful information in error messages
  3. Appropriate logging: Use logging for debugging, not for production
  4. Smart retries: Only retry on recoverable errors (5xx)
  5. 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

Resources
Blog
Find us on social networks
For complaints, please contact via email denuncias@retorna.app
We belong to the Financial Analysis Unit (UAF).
Supervised by
Registration number is C100000211.
Members of
With the support ofCon el apoyo de
Copyright © Retorna Holding Spa 2024