Skip to content

Error Handling

Best practices for handling errors across all SDKs.

Error Types

All SDKs provide typed errors:

Error TypeDescription
IOFErrorBase API error
ValidationErrorInvalid request data
AuthenticationErrorInvalid credentials
RateLimitErrorRate limit exceeded
NetworkErrorConnection issues

TypeScript/JavaScript

typescript
import { IslamicOpenFinance, IOFError, ValidationError } from "@iof/sdk";

try {
  const contract = await iof.contracts.create({ ... });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error("Validation failed:");
    error.details.forEach(d => {
      console.error(`  ${d.field}: ${d.message}`);
    });
  } else if (error instanceof IOFError) {
    console.error(`API error: ${error.code} - ${error.message}`);
  } else {
    console.error("Unexpected error:", error);
  }
}

Python

python
from iof import IslamicOpenFinance, IOFError, ValidationError

try:
    contract = iof.contracts.create(...)
except ValidationError as e:
    print("Validation failed:")
    for detail in e.details:
        print(f"  {detail['field']}: {detail['message']}")
except IOFError as e:
    print(f"API error: {e.code} - {e.message}")
except Exception as e:
    print(f"Unexpected error: {e}")

Go

go
contract, err := client.Contracts.Create(ctx, params)
if err != nil {
    var iofErr *iof.Error
    if errors.As(err, &iofErr) {
        fmt.Printf("API error: %s - %s\n", iofErr.Code, iofErr.Message)

        if iofErr.Code == "VALIDATION_ERROR" {
            for _, detail := range iofErr.Details {
                fmt.Printf("  %s: %s\n", detail.Field, detail.Message)
            }
        }
    } else {
        fmt.Printf("Unexpected error: %v\n", err)
    }
}

Java

java
try {
    Contract contract = client.contracts().create(params);
} catch (ValidationException e) {
    System.err.println("Validation failed:");
    for (var detail : e.getDetails()) {
        System.err.println("  " + detail.getField() + ": " + detail.getMessage());
    }
} catch (IOFException e) {
    System.err.println("API error: " + e.getCode() + " - " + e.getMessage());
} catch (Exception e) {
    System.err.println("Unexpected error: " + e.getMessage());
}

Retry Strategies

Exponential Backoff

typescript
async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3
): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error instanceof RateLimitError) {
        const delay = Math.pow(2, attempt) * 1000;
        await sleep(delay);
        continue;
      }
      throw error;
    }
  }
  throw new Error("Max retries exceeded");
}

// Usage
const contract = await withRetry(() =>
  iof.contracts.create({ ... })
);

Idempotency Keys

typescript
const contract = await iof.contracts.create(
  { ... },
  { idempotencyKey: "unique-request-id" }
);

Best Practices

  1. Always handle errors - Don't let errors fail silently
  2. Log request IDs - Include requestId in error logs
  3. Use typed errors - Check error types for specific handling
  4. Implement retries - Retry transient errors with backoff
  5. Use idempotency - Prevent duplicate operations

Next Steps

Licensed under the Apache License 2.0