Exception Hierarchy
All exceptions thrown by the SDK when API calls fail. Every exception includes the HTTP status code, a Flare error code, and a server-assigned request ID for correlation.
Namespace: Zeridion.Flare · Assembly: Zeridion.Flare.dll
Hierarchy
FlareApiException
The base exception for all Flare API errors. Catch this to handle any API failure generically.
public class FlareApiException : Exception
{
public int StatusCode { get; }
public string ErrorCode { get; }
public string? RequestId { get; }
}
| Property | Type | Description |
|---|---|---|
StatusCode | int | HTTP status code returned by the API (e.g. 400, 500). |
ErrorCode | string | Flare error code (e.g. "job_not_found", "invalid_request"). |
RequestId | string? | Server-assigned request ID for support and debugging. |
The Message property (inherited from Exception) contains the human-readable error description from the API.
Thrown for any non-success HTTP response that does not match one of the specific subtypes below (e.g. 400 Bad Request, 500 Internal Server Error).
FlareAuthenticationException
Thrown when the API returns 401 Unauthorized — the API key is invalid, expired, or missing.
public sealed class FlareAuthenticationException : FlareApiException
{
// StatusCode is always 401
}
When it is thrown:
- The
ApiKeyinZeridionFlareOptionsis incorrect or has been revoked - The
Authorizationheader is missing (SDK misconfiguration)
Common error codes: "unauthorized"
try
{
await jobs.EnqueueAsync<SendEmail>(payload);
}
catch (FlareAuthenticationException ex)
{
logger.LogCritical("Invalid API key: {Error} (request: {RequestId})",
ex.Message, ex.RequestId);
// Alert ops — this is a configuration issue, not a transient error
}
FlareNotFoundException
Thrown when the API returns 404 Not Found — the job or resource does not exist.
public sealed class FlareNotFoundException : FlareApiException
{
// StatusCode is always 404
}
When it is thrown:
ContinueWithAsyncreferences a parent job that does not exist (API returns 422parent_not_found)CancelAsyncorRetryAsyncis called with a job ID that does not exist
GetStatusAsync does not throw FlareNotFoundException. It returns null when the job does not exist, allowing callers to check without try/catch.
Common error codes: "job_not_found"
try
{
await jobs.ContinueWithAsync<SendReceipt>(parentJobId, payload);
}
catch (FlareNotFoundException ex)
{
logger.LogWarning("Parent job {ParentId} not found: {Error}",
parentJobId, ex.Message);
}
FlareConflictException
Thrown when the API returns 409 Conflict — a state conflict or duplicate was detected.
public sealed class FlareConflictException : FlareApiException
{
// StatusCode is always 409
}
When it is thrown:
- An
IdempotencyKeymatches an existing job (duplicate prevention) - A state transition is invalid (e.g. cancelling an already-completed job, though
CancelAsynccatches this and returnsfalseinstead) - A worker mismatch during acknowledgement
Common error codes: "idempotency_conflict", "invalid_state", "worker_mismatch"
try
{
await jobs.EnqueueAsync<ProcessPayment>(payload, new JobOptions
{
IdempotencyKey = $"payment:{orderId}"
});
}
catch (FlareConflictException ex)
{
logger.LogInformation("Duplicate job prevented by idempotency key: {Error}",
ex.Message);
// This is expected behavior — the job already exists
}
CancelAsync and RetryAsync do not throw FlareConflictException on 409 — they return false instead, making them safe to call without try/catch.
FlareRateLimitException
Thrown when the API returns 429 Too Many Requests — the rate limit for your API key has been exceeded.
public sealed class FlareRateLimitException : FlareApiException
{
public int Limit { get; }
public int Remaining { get; }
public DateTimeOffset? ResetAt { get; }
}
| Property | Type | Description |
|---|---|---|
Limit | int | Maximum requests allowed per window (from X-RateLimit-Limit). |
Remaining | int | Remaining requests in the current window (from X-RateLimit-Remaining). |
ResetAt | DateTimeOffset? | When the rate limit window resets (from X-RateLimit-Reset). |
When it is thrown:
- Your API key has exceeded its rate limit tier
Common error codes: "rate_limit_exceeded"
try
{
await jobs.EnqueueAsync<SendEmail>(payload);
}
catch (FlareRateLimitException ex)
{
logger.LogWarning(
"Rate limited: {Limit} req/window, {Remaining} remaining, resets at {ResetAt}",
ex.Limit, ex.Remaining, ex.ResetAt);
if (ex.ResetAt.HasValue)
{
var delay = ex.ResetAt.Value - DateTimeOffset.UtcNow;
if (delay > TimeSpan.Zero)
await Task.Delay(delay);
}
}
Comprehensive catch pattern
Handle all exception types from most specific to least specific:
try
{
var jobId = await jobs.EnqueueAsync<ProcessOrder>(orderPayload, new JobOptions
{
IdempotencyKey = $"order:{order.Id}"
});
logger.LogInformation("Enqueued job {JobId}", jobId);
}
catch (FlareRateLimitException ex)
{
logger.LogWarning("Rate limited, retry after {ResetAt}", ex.ResetAt);
// Back off and retry, or queue locally
}
catch (FlareConflictException)
{
logger.LogInformation("Duplicate order job — already enqueued");
// Safe to ignore — idempotency key prevented duplicate work
}
catch (FlareAuthenticationException ex)
{
logger.LogCritical("API key invalid: {Error}", ex.Message);
// Configuration error — alert immediately
throw;
}
catch (FlareApiException ex)
{
logger.LogError("Flare API error {StatusCode}: {Error} (request: {RequestId})",
ex.StatusCode, ex.Message, ex.RequestId);
// Unexpected API error — log and decide whether to retry
}
See also
- Error handling guide — patterns for handling failures in production
- Idempotency guide — preventing duplicate work with idempotency keys
- IJobClient — the methods that throw these exceptions