Class AnkaSecureSdkException

java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
co.ankatech.ankasecure.sdk.exception.AnkaSecureSdkException
All Implemented Interfaces:
Serializable
Direct Known Subclasses:
DestinationExistsException, Http2RequiredException, LocalFileException, StaleSidecarException, StreamIntegrityException, StreamWriteFailedException, TokenRevokedException

public class AnkaSecureSdkException extends RuntimeException
A uniform, localization-ready exception thrown by all public ANKASecure SDK APIs.

This exception carries HTTP error information returned by a remote service, including status code, response body, and an optional SDK error code. It also allows attaching arbitrary context data for richer diagnostics.

Handling SDK Exceptions

Error Code-Based Handling


 try {
     EncryptResult result = sdk.encrypt("my-key", plaintext);
 } catch (AnkaSecureSdkException e) {
     switch (e.getErrorCode()) {
         case TIMEOUT:
         case IO:
             // Network failure: retry with backoff
             retryWithBackoff(operation);
             break;
         case STATEFUL_KEY_BUSY:
             // Transient: retry, honoring the server-provided Retry-After hint when present
             Long retryAfterSeconds = e.getRetryAfterSeconds();
             Thread.sleep((retryAfterSeconds != null ? retryAfterSeconds : 1L) * 1000L);
             break;
         case STATEFUL_KEY_EXHAUSTED:
             // Permanent for this key: rotate it instead of retrying
             logger.error("Key '{}' has no one-time signature left", e.getContext().get("kid"));
             break;
         default:
             // Generic handling
             logger.error("API error: {} (HTTP {})", e.getMessage(), e.getHttpStatus());
     }
 }
 

HTTP Status-Based Handling


 try {
     EncryptResult result = sdk.encrypt(kid, plaintext);
 } catch (AnkaSecureSdkException e) {
     if (e.getHttpStatus() == 404) {
         // Key not found for this tenant
         logger.error("Key '{}' does not exist", kid);
     } else if (e.getHttpStatus() >= 500) {
         // Server error, implement retry logic
         retryWithBackoff(() -> sdk.encrypt(kid, plaintext));
     }
 }
 

Contextual Information

Use getContext() for detailed diagnostics:


 try {
     DecryptResult result = sdk.decrypt(jwe);
 } catch (AnkaSecureSdkException e) {
     Map<String, String> context = e.getContext();
     logger.error("Decryption failed for kid={}, algorithm={}, status={}",
         context.get("kid"),
         context.get("algorithm"),
         e.getHttpStatus());
 }
 

Base Type for SDK-Thrown Exceptions

This is the documented base type of the SDK's public exception hierarchy. More specific client-side conditions are modelled as subclasses (for example DestinationExistsException, StreamIntegrityException, StaleSidecarException), so a single catch (AnkaSecureSdkException e) catches every failure the SDK raises. For a purely client-side subclass (no HTTP round-trip), getHttpStatus() is 0, getResponseBody() is null, and getContext() is empty.

See Also:
  • Field Details

    • MAX_RETRY_AFTER_SECONDS

      public static final long MAX_RETRY_AFTER_SECONDS
      The largest Retry-After hint, in seconds, the SDK reports: one hour.

      Retry-After is a response header, so its value is whatever the far side — or anything between the client and the platform — sent. The platform's own hints are seconds to a minute; a value above one hour is never a wait a caller should honour blindly, and an unbounded value multiplied into milliseconds overflows. A larger header value is reported as this bound, so getRetryAfterSeconds() never exceeds it.

      See Also:
  • Constructor Details

    • AnkaSecureSdkException

      public AnkaSecureSdkException(String message, int httpStatus, String responseBody, Throwable cause, Map<String,String> context)
      Constructs a new SDK exception with the specified message, HTTP status, response body, cause, and context. The error code is initialized to SdkErrorCode.UNKNOWN and retryAfterSeconds to null.
      Parameters:
      message - the detail message for this exception
      httpStatus - the HTTP status code associated with this error
      responseBody - the body of the HTTP response returned by the remote service
      cause - the underlying cause of this exception (may be null)
      context - additional context information as key-value pairs
    • AnkaSecureSdkException

      public AnkaSecureSdkException(String message, int httpStatus, String responseBody, Throwable cause, Map<String,String> context, SdkErrorCode errorCode, Long retryAfterSeconds)
      Constructs a new SDK exception with the specified message, HTTP status, response body, cause, context, a specific SDK error code, and the server-provided Retry-After hint.
      Parameters:
      message - the detail message for this exception
      httpStatus - the HTTP status code associated with this error
      responseBody - the body of the HTTP response returned by the remote service
      cause - the underlying cause of this exception (may be null)
      context - additional context information as key-value pairs
      errorCode - the SdkErrorCode representing the specific error condition
      retryAfterSeconds - the server-provided Retry-After header value in integer seconds, or null when the server did not send one
  • Method Details

    • getHttpStatus

      public int getHttpStatus()
      Returns the HTTP status code returned by the remote service.
      Returns:
      the HTTP status code
    • getResponseBody

      public String getResponseBody()
      Returns the full response body returned by the remote service.
      Returns:
      the HTTP response body as a string
    • getContext

      public Map<String,String> getContext()
      Returns additional context information provided with this exception.
      Returns:
      an unmodifiable map of context key-value pairs
    • getErrorCode

      public SdkErrorCode getErrorCode()
      Returns the specific SDK error code categorizing this failure.
      Returns:
      the SdkErrorCode for this exception
    • getRetryAfterSeconds

      public Long getRetryAfterSeconds()
      Returns the server-provided Retry-After hint, in integer seconds.

      The platform emits this header on refusals that are expected to clear — among them a 502/504 while a server-side circuit breaker toward an upstream dependency is open, a 503 for a dependency or key-protection backend that is not ready yet, a 429 from the token endpoint, and a 409 whose error code is SdkErrorCode.STATEFUL_KEY_BUSY. Callers implementing retry logic should wait at least this many seconds before the next attempt.

      The value is bounded: it lies in [0, MAX_RETRY_AFTER_SECONDS] (one hour). A larger header value — including an integer too large for long — is reported as MAX_RETRY_AFTER_SECONDS, so seconds * 1000L cannot overflow. A negative, malformed or HTTP-date value is not a hint and is reported as null.

      Returns:
      the Retry-After value in seconds, at most MAX_RETRY_AFTER_SECONDS, or null when the server did not provide a usable one