Skip to main content

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; }
}
PropertyTypeDescription
StatusCodeintHTTP status code returned by the API (e.g. 400, 500).
ErrorCodestringFlare error code (e.g. "job_not_found", "invalid_request").
RequestIdstring?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 ApiKey in ZeridionFlareOptions is incorrect or has been revoked
  • The Authorization header 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:

  • ContinueWithAsync references a parent job that does not exist (API returns 422 parent_not_found)
  • CancelAsync or RetryAsync is called with a job ID that does not exist
note

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 IdempotencyKey matches an existing job (duplicate prevention)
  • A state transition is invalid (e.g. cancelling an already-completed job, though CancelAsync catches this and returns false instead)
  • 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
}
note

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; }
}
PropertyTypeDescription
LimitintMaximum requests allowed per window (from X-RateLimit-Limit).
RemainingintRemaining requests in the current window (from X-RateLimit-Remaining).
ResetAtDateTimeOffset?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