NexusException, which extends RuntimeException. You can catch the base class to handle all SDK errors in one place, or catch specific subclasses for fine-grained control.
Exception reference
| Exception | When it is thrown | Thrown by |
|---|---|---|
NexusException | Base class for all SDK errors. Also thrown directly for unexpected HTTP status codes. | Various |
NexusInitException | Initial sync failed at client creation. Wraps the underlying cause. | NexusClient.create |
NexusUnauthorizedException | HTTP 401 - invalid API key, endpoint mismatch, or expired session that could not be refreshed. | sync, NexusClient.create |
NexusNotFoundException | HTTP 404 - the service was not found. Usually indicates a wrong baseUrl. | sync, NexusClient.create |
NexusPublicKeyException | A wxp_... key was used to call getSecret or getSecretFilePath. Public keys cannot access secrets. | getSecret, getSecretFilePath |
NexusSecretNotFoundException | The requested secret key is not in the current snapshot. | getSecret, getSecretFilePath |
NexusBillingException | HTTP 402 - the tenant has overdue invoices. Sync is paused; observer.onBillingOverdue() is also called. | sync |
NexusServiceKindMismatchException | getSecret was called on a frontend service, which never syncs secrets. | getSecret |
NexusWifNotConfiguredException | WIF is enabled but no token could be resolved for the current environment. | NexusClient.create (during session init) |
NexusWifTokenExchangeFailedException | The OIDC token was obtained but the POST /v1/auth/token-exchange request failed. | NexusClient.create, background session refresh |
NexusSessionExpiredException | WIF session expired and the background refresh failed. | Background session refresh |
NexusAbAddonNotAvailableException | HTTP 403 from evaluateAB - the A/B add-on is not active for this project. | evaluateAB |
NexusQuarantinedException | HTTP 429 with a quarantine payload - the service is temporarily banned from calling the API. Contains reason: String and expiresAt: Instant. | sync |
NexusRateLimitedException | HTTP 429 on write endpoints - contains retryAfter: Duration for the recommended retry delay. | setSecret, deleteSecret, deleteSecretVersion |
Catching exceptions at client creation
val client = try {
NexusClient.create(config)
} catch (e: NexusInitException) {
// initial sync failed - could be network, DNS, or server error
logger.error("Could not connect to Nexus", e)
exitProcess(1)
} catch (e: NexusUnauthorizedException) {
// bad API key or wrong baseUrl
logger.error("Nexus auth failed - check NEXUS_API_KEY and baseUrl")
exitProcess(1)
} catch (e: NexusNotFoundException) {
// baseUrl points to a non-existent service
logger.error("Nexus service not found - check baseUrl")
exitProcess(1)
} catch (e: NexusBillingException) {
// tenant billing overdue
logger.warn("Nexus: billing overdue, running on last cached values")
// continue with empty cache or exit depending on your policy
}
Catching secret access errors
val secret = try {
client.getSecret("stripe_secret_key")
} catch (e: NexusPublicKeyException) {
// public key used - this is a programming error
throw IllegalStateException("Use a secret key for backend services", e)
} catch (e: NexusServiceKindMismatchException) {
// frontend service - secrets not available
throw IllegalStateException("Frontend services cannot access secrets", e)
} catch (e: NexusSecretNotFoundException) {
// key does not exist in the current snapshot
logger.warn("Secret 'stripe_secret_key' not found, using env fallback")
System.getenv("STRIPE_SECRET_KEY") ?: error("No fallback available")
}
Catching A/B errors
val results = try {
client.evaluateAB(listOf("checkout_v2"), userId = "user-123")
} catch (e: NexusAbAddonNotAvailableException) {
// add-on not active - fall back to default
mapOf("checkout_v2" to false)
} catch (e: NexusException) {
// any other SDK error
logger.warn("evaluateAB failed: ${e.message}")
mapOf("checkout_v2" to false)
}
WIF-specific errors
val config = NexusConfig(
baseUrl = "https://my-service.westyx.dev",
wif = WifConfig(enabled = true, provider = "kubernetes"),
)
val client = try {
NexusClient.create(config)
} catch (e: NexusWifNotConfiguredException) {
// Kubernetes service account token not found at expected path
logger.error("WIF token not available: ${e.message}")
exitProcess(1)
} catch (e: NexusWifTokenExchangeFailedException) {
// Token obtained but exchange endpoint rejected it
logger.error("WIF token exchange failed: ${e.message}")
exitProcess(1)
} catch (e: NexusInitException) {
logger.error("Nexus init failed", e.cause)
exitProcess(1)
}
Quarantine
When the SDK receives a quarantine response (HTTP 429 with a JSON body containing"error": "quarantined"), it throws NexusQuarantinedException from sync() and also calls observer.onQuarantined(reason, expiresAt). For the SSE stream, the quarantine is handled automatically - the stream sleeps until expiresAt and reconnects without incrementing the failure counter.
try {
client.sync()
} catch (e: NexusQuarantinedException) {
println("Quarantined: ${e.reason}, lifts at ${e.expiresAt}")
// TTL background sync will also pause until expiresAt
}
