RollupError with a stable code and a message meant for you, not for the person. Errors from Rollup’s server carry the server’s error code at the start of the message. See RollupError for every code.
simulatorUnsupported
simulatorUnsupported
configure throws this in the iOS Simulator. The SDK needs a real iPhone with iOS 26 or later: Apple Vision analysis does not run in the Simulator. Your app still builds for the Simulator; skip Rollup there and test it on a device.missingRequirement
missingRequirement
configure throws this when your Info.plist lacks an entry the SDK needs. The message names each one: NSPhotoLibraryUsageDescription, the two BGTaskSchedulerPermittedIdentifiers entries, or processing in UIBackgroundModes. See the Quickstart.notConfigured
notConfigured
Call
Rollup.configure(publishableKey:indexing:) before any other call. configure also throws this when the key does not start with rk_.appPendingApproval: the app is waiting for approval
appPendingApproval: the app is waiting for approval
Your app exists in the dashboard but Rollup has not approved it yet, so the server answers every request with 403
app_pending. The SDK throws appPendingApproval and reports the state .failed with it while nothing is running. Indexing that needs the server waits; search over an index already on the iPhone keeps working. The SDK does not lock, and asks again at its next check: at launch, at the start of a background run, or once a day. Check your app’s status in the dashboard.accessRevoked
accessRevoked
Your app’s key stopped working: the key is unknown or past its grace period, the app is disabled or revoked, or your developer account is not approved. The SDK stops indexing, keeps the index locked, and unlocks when access returns. See Keys and revocation.
quotaExceeded: the monthly token budget is used
quotaExceeded: the monthly token budget is used
The server answers
query and profile with 429 app_quota_exceeded, and the SDK throws quotaExceeded, without retrying. query and profile stop until the first day of the next month (UTC), or until Rollup raises your app’s budget. The message names the reset date. Search and indexing keep working. See Limits and budgets.rateLimited
rateLimited
A device or your app sent too many requests in 5 minutes (429
rate_limited). The SDK throws rateLimited, which is retryable; wait retryAfter seconds when it is set, or a little while, and try again. See Limits and budgets.appAttestFailed: device registration fails
appAttestFailed: device registration fails
The SDK registers each install with Rollup the first time it needs the server, with an App Attest attestation.
appAttestFailed means App Attest could not vouch for this install, and its message names the likely cause. Check that:- your target has the App Attest capability (
com.apple.developer.devicecheck.appattest-environment), whichconfigurecannot check, - the Team ID and bundle ID of your app in the dashboard match the build you are running,
- you are on a real iPhone, not the Simulator.
network error instead; try again later.noIndex
noIndex
Search, query and profile have nothing to read yet. Wait until
Rollup.shared.indexing.state.isSearchable is true. If the state is needsPhotoAccess, call requestPhotoAccess first.photoAccessDenied, or the state stays needsPhotoAccess
photoAccessDenied, or the state stays needsPhotoAccess
The person declined Photos access, or turned it off in Settings. Without access the SDK indexes nothing and deletes an index it already had, so
search, query and profile throw photoAccessDenied and the state is needsPhotoAccess. requestPhotoAccess still returns the person’s answer. Ask the person to allow access in Settings. Limited access is not denied: the SDK indexes the photos the person shared.Indexing stops when the app leaves the screen
Indexing stops when the app leaves the screen
Indexing continues in the background only when the person started it: through the Photos grant in
requestPhotoAccess, or through indexing.start() called from a tap. Other runs stop safely when your app leaves the screen, and the SDK finishes the index later in a background processing task or the next time your app is on screen. See Background indexing.
