EncoreError
EncoreError is a sealed, nested enum. Errors surface by being thrown from try await placement(_:).show() (and other throws APIs like revokeEntitlements()) — they are not delivered as a NotGrantedReason. User dismissals and “no offers” are business outcomes, not errors; see NotGrantedReason.
Never block user actions on an SDK error. Always provide a fallback path so the user can complete their intended action — your onPassthrough handler already runs for not-granted outcomes; wrap try await show() in do/catch and proceed on error too.
Definition
public enum EncoreError: Error, LocalizedError, Sendable {
case transport(TransportError) // "The road is broken" — connectivity
case `protocol`(ProtocolError) // "The language failed" — HTTP/API
case integration(IntegrationError) // "SDK misused" — config/programmer error
case domain(String) // Client business-rule violation (message only)
public enum TransportError: Error, Sendable {
case network(Error) // No connectivity, timeout, connection failed
case persistence(Error) // Local storage read/write failure
}
public enum ProtocolError: Error, Sendable {
case http(status: Int, message: String?) // Non-2xx, body unreadable
case api(status: Int, code: String?, message: String) // Structured server error
case decoding(Error) // 2xx body didn't match schema
}
public enum IntegrationError: Error, Sendable {
case notConfigured // configure() not called before use
case invalidApiKey // Empty / malformed API key
case invalidURL // Failed to construct a request URL
}
}
Top-level cases
| Case | Associated value | Meaning |
|---|
.transport(TransportError) | nested | Connectivity layer failed (network or local persistence). |
.protocol(ProtocolError) | nested | The request reached the server but the exchange failed (bad status, server error, or undecodable body). |
.integration(IntegrationError) | nested | The SDK was misused or misconfigured. |
.domain(String) | String | A client-side business-rule violation, carrying a human-readable message. |
Nested cases
| Case | Associated values | Description |
|---|
.transport(.network(Error)) | underlying Error | No internet, timeout, or connection failure. |
.transport(.persistence(Error)) | underlying Error | Local storage (cache/outbox) read or write failed. |
.protocol(.http(status:message:)) | Int, String? | Non-2xx response with an unreadable/unexpected body. |
.protocol(.api(status:code:message:)) | Int, String?, String | Server returned a structured error (its own domain error). |
.protocol(.decoding(Error)) | underlying Error | A 2xx response body didn’t match the expected schema. |
.integration(.notConfigured) | none | configure(apiKey:) was not called before use. |
.integration(.invalidApiKey) | none | The API key was empty or malformed. |
.integration(.invalidURL) | none | The SDK could not build a valid request URL. |
.domain(String) | String | Client business-rule violation; the string describes it. |
Helpers
Every EncoreError conforms to LocalizedError, so errorDescription gives a developer-readable summary. transport and protocol(.decoding) errors also expose the wrapped system error via the underlying property:
if let underlying = encoreError.underlying {
// The original URLSession / decoding error, when one exists.
}
Handling errors
func cancelTapped() {
Task {
do {
let result = try await Encore.placement("cancel_flow").show()
switch result {
case .granted(let entitlement):
applyEntitlement(entitlement)
case .notGranted:
// User dismissed or no offers — proceed with the original action.
proceedWithCancellation()
}
} catch let error as EncoreError {
switch error {
case .integration(.notConfigured):
assertionFailure("Call Encore.shared.configure(apiKey:) at launch")
case .transport(.network(let underlying)):
Logger.log("Network error: \(underlying.localizedDescription)")
case .protocol(.api(_, let code, let message)):
Logger.log("API error (\(code ?? "unknown")): \(message)")
default:
Logger.log(error.errorDescription ?? "Encore error")
}
// Always let the user proceed.
proceedWithCancellation()
} catch {
proceedWithCancellation()
}
}
}
- NotGrantedReason — business outcomes (dismiss, no offers, experiment control, unsupported OS). These are not errors.
- PresentationResult — the value returned by
try await show().
The most common “failure” is not an error at all — it’s the user declining an offer, surfaced as a NotGrantedReason. Reserve do/catch for genuine transport, protocol, and integration failures.