Errors

Every error type of the Folio SDK, where it reaches your code and what each case means.

Preview

This page describes a pre-release version of the SDK. Names, versions and APIs on this page can change before the release.

The SDK reports a failure in one of two ways:

  • A failed call. A call on the runtime or on a store fails at once: creating the runtime, calling a static helper, mounting a store, dispatching an action or subscribing, and on the web also reading state while no listener is subscribed. The call throws.
  • Store state. The work behind an action fails later, for example a request that Folio rejects. dispatch has already returned; the failure appears in the state of the store.
Where it reaches youType
mount, dispatch, subscribe, state on the webA thrown error; see A failed call
FolioSdk.create, SessionUiModel.errorSessionStartError
FolioSdk.barcodeImage, computeMetrics, rotateImageA thrown error whose message is an ImageProcessingError text
new and parse of the calendar values, Instant.fromEpochMillisA thrown error whose message is an InvalidCalendarValue text
AttachmentRef.getBytes()A thrown error whose message is an AttachmentReadError text
AuthUiModel.flowAuthError
VaultUiModel.errorVaultErrorView, a wrapper
InquiryUiModel.errorInquiryErrorView, a projection
InquiryLifecycle.FailedInquiryError
MrtdUiModel.errorMrtdUiError
FolioDocumentUiModel.errorA localized String; see Folio documents
FolioDocumentListUiModel.receptionFailed with a localized text and retry; see Reception
LogsUiModel.Failed, InteractionRecording.Rejected, SdkLogger callsLogError
Your IdentityRecordMapperIdentityMappingError
The embed loader's onLifecycleInquiryError of type EMBED

Naming across platforms

Every error type is generated from one definition, so the cases are the same on every platform. This page names cases as Kotlin does. The error types come in two shapes.

Tagged cases. InquiryError, SessionStartError, AuthError, VaultError, MrtdUiError, ImageProcessingError, InvalidCalendarValue, AttachmentReadError, LogError and the reasons OtpErrorReason, GovIdErrorReason, SelfieErrorReason and EmbedFailure:

PlatformShapeCase with fieldsCase without fields
SwiftAn enum with associated values, cases in lowerCamelCase with labeled fields.recordMapping(message: message).invalidEntry
KotlinA sealed class: a data class per case with fields, a data object per case withoutInquiryError.RecordMapping(message)InquiryError.InvalidEntry
TypeScriptA value with a type in SCREAMING_SNAKE_CASE and its fields under value{ type: 'RECORD_MAPPING', value: { message } }{ type: 'INVALID_ENTRY' }

In TypeScript each of these types also has a factory or constant per case in lowerCamelCase, such as InquiryError.recordMapping(message) and InquiryError.invalidEntry.

ImageProcessingError, InvalidCalendarValue and AttachmentReadError are exported in these shapes, but no call hands your app one of their values. A call that fails because of one of them throws a failed call error whose message is the text of the case.

ImageProcessingError carries its text in a single field value: .insufficientData(value:) in Swift, ImageProcessingError.InsufficientData(value) in Kotlin, and { type: 'INSUFFICIENT_DATA', value: '<text>' } in TypeScript, where value is the string itself, not an object.

Codes. CoreError is a plain enumeration: an enum with a UInt8 raw value in Swift (.invalidComponent), an enum class with a value in Kotlin (CoreError.INVALID_COMPONENT), and a string in TypeScript ('INVALID_COMPONENT', also CoreError.INVALID_COMPONENT).

In TypeScript, match a case by its type:

TypeScript
if (lifecycle.type === 'FAILED' && lifecycle.value.error.type === 'RECORD_MAPPING') {
    reportMapperFailure(lifecycle.value.error.value.message);
}

The inquiry UI needs no such check: it shows the notice in InquiryUiModel.failure, whose texts the SDK has already chosen. See Failure notice.

A failed call

A call on a store fails because of a CoreError, FolioSdk.create because of a SessionStartError, an image helper because of an ImageProcessingError, a calendar value constructor because of an InvalidCalendarValue and getBytes() of an attachment because of an AttachmentReadError. In every case the call throws the platform's error type, whose message describes the failure; the SDK error itself is not handed to your app:

PlatformWhat the call throws
iOSFolioSDKError, with code and message. Call the method with try. After close(), every call on a store throws FolioSDKError with the message Handle already released.
AndroidFolioSDKException, a RuntimeException with code and message. After close(), every call on a store throws IllegalStateException with the message Handle has been closed.
WebFolioSDKError, an Error with message, the numeric status and lastError, and their names statusName and lastErrorName. Reading state calls into the SDK, and so can throw, only while no listener is subscribed; otherwise it returns the last state. When the store's state stream failed, reading state throws that error. After close(), dispatch and subscribe() without a listener throw an Error such as MrtdStore has been disposed, reading state returns the last state, and subscribe with a listener function returns an unsubscribe that does nothing.
Swift
do {
    try store.dispatch(action: .close)
} catch let error as FolioSDKError {
    log(error.message)
} catch {
    log(String(describing: error))
}

On Android, rememberFolioSdk does not throw: it reports a failed create as FolioSdkStartup.Failed with the exception in error. See Runtime and stores.

On the web, message is the SDK's message for the failure, or the status name when the SDK recorded none. The SDK also prints every FolioSDKError it throws with console.error, prefixed [FolioSDK]; see Create the runtime.

A store keeps its state current by reading a subscription in the background. When that stream fails, the error is kept in streamError: a @Published Error? on iOS and a StateFlow<Throwable?> on Android. On the web the store keeps it and throws it from state.

Error codes

The code of FolioSDKError on iOS and of FolioSDKException on Android, and status and lastError of FolioSDKError on the web, are codes of the bridge between your app and the SDK's native code. The numbers are the same on every platform:

CodeNameKotlin constantTypeScript
0OkFolioSDKException.OKFolioSDKErrorCode.Ok
1InvalidArgumentFolioSDKException.INVALID_ARGUMENTFolioSDKErrorCode.InvalidArgument
2NullPointerFolioSDKException.NULL_POINTERFolioSDKErrorCode.NullPointer
3BufferTooSmallFolioSDKException.BUFFER_TOO_SMALLFolioSDKErrorCode.BufferTooSmall
4InvalidUtf8FolioSDKException.INVALID_UTF8FolioSDKErrorCode.InvalidUtf8
5TypeMismatchFolioSDKException.TYPE_MISMATCHFolioSDKErrorCode.TypeMismatch
6InvalidHandleFolioSDKException.INVALID_HANDLEFolioSDKErrorCode.InvalidHandle
7NotSupportedFolioSDKException.NOT_SUPPORTEDFolioSDKErrorCode.NotSupported
8InternalErrorFolioSDKException.INTERNAL_ERRORFolioSDKErrorCode.InternalError
9PanicFolioSDKException.PANICFolioSDKErrorCode.Panic
10TimeoutFolioSDKException.TIMEOUTFolioSDKErrorCode.Timeout
11CancelledFolioSDKException.CANCELLEDFolioSDKErrorCode.Cancelled
12NotFoundFolioSDKException.NOT_FOUNDFolioSDKErrorCode.NotFound
13AlreadyExistsFolioSDKException.ALREADY_EXISTSFolioSDKErrorCode.AlreadyExists
14PermissionDeniedFolioSDKException.PERMISSION_DENIEDFolioSDKErrorCode.PermissionDenied
15IoErrorFolioSDKException.IO_ERRORFolioSDKErrorCode.IoError
16RefcountOverflowFolioSDKException.REFCOUNT_OVERFLOWFolioSDKErrorCode.RefcountOverflow
17CallbackDestroyedFolioSDKException.CALLBACK_DESTROYEDFolioSDKErrorCode.CallbackDestroyed
18WrongThreadFolioSDKException.WRONG_THREADFolioSDKErrorCode.WrongThread
19ReentrancyViolationFolioSDKException.REENTRANCY_VIOLATIONFolioSDKErrorCode.ReentrancyViolation
20JniExceptionFolioSDKException.JNI_EXCEPTIONFolioSDKErrorCode.JniException
21ForgedFolioSDKException.FORGEDFolioSDKErrorCode.Forged
22MisalignedFolioSDKException.MISALIGNEDFolioSDKErrorCode.Misaligned
23BorrowConflictFolioSDKException.BORROW_CONFLICTFolioSDKErrorCode.BorrowConflict
255UnknownFolioSDKException.UNKNOWNFolioSDKErrorCode.Unknown

In Swift, code is a FolioSDKErrorCode; compare its number, error.code.rawValue, a UInt32. In Kotlin, code is an Int and the constants are members of FolioSDKException. In TypeScript, FolioSDKErrorCode is exported from @folio/sdk, and statusName and lastErrorName hold the names from this table, or unnamed(<code>) for a number the table does not list.

BorrowConflict means that the call needed an SDK object in a way that conflicts with its current use: exclusive access to an object that is in use elsewhere, or any access to an object that another call holds exclusively. Its message is handle has conflicting shared or exclusive access.

A call that fails because of an SDK error, such as a CoreError, a SessionStartError, an ImageProcessingError, an InvalidCalendarValue or an AttachmentReadError, throws with code InternalError (8); the SDK error shows only in message, as its text. The numeric codes of CoreError are not bridge codes.

Bridge failures

Some interfaces of the SDK are implemented by your app, such as the IdentityRecordMapper you pass to FolioSdk.create. The SDK reports a failure of such an implementation to a bridge error handler when a method that cannot return an error throws, or when the arguments or the return value of a method cannot be converted. It reports the failure of a store's stream to the same handler. The handler receives the site, <Interface>.<method> or <Store>.stream, and the error.

PlatformHandlerDefault
iOSFolioSDKCore.bridgeErrorHandler: (@Sendable (String, Error) -> Void)?NSLog
AndroidFolioSDKCore.bridgeErrorHandler: ((String, Throwable) -> Unit)?System.err
WebFolioSDKDiagnostics.bridgeErrorHandler?: (site: string, error: Error) => voidconsole.error

Set the handler to send these failures to your own logging, for example to the SDK logger. An error that a method can return, such as an IdentityMappingError from map, reaches the SDK as that error and is not reported, and neither is cancellation. A store stream failure also stays visible in the store's streamError, as described in A failed call.

CoreError

The error of the store runtime. Each case has a fixed numeric code: the raw value in Swift and value in Kotlin.

CaseCodeSwiftKotlinTypeScriptMeaning
InvalidComponent0.invalidComponentCoreError.INVALID_COMPONENT'INVALID_COMPONENT'The call targets a component that does not match or no longer exists.
DeterminismViolation1.determinismViolationCoreError.DETERMINISM_VIOLATION'DETERMINISM_VIOLATION'The runtime detected a breach of its internal consistency rules.
NotInitialized3.notInitializedCoreError.NOT_INITIALIZED'NOT_INITIALIZED'The runtime is not initialized.
StoreOverflow4.storeOverflowCoreError.STORE_OVERFLOW'STORE_OVERFLOW'The action could not be queued: the runtime's queue is full or the store loop stopped.
TimelineUnavailable5.timelineUnavailableCoreError.TIMELINE_UNAVAILABLE'TIMELINE_UNAVAILABLE'The debug history cannot be read or written, for example after the runtime has closed it. A release build records no debug history; in a build with the timeline feature (the debug profile), the runtime keeps it in memory, up to 2,048 entries, and drops it when it shuts down.
TimelineCorrupted6.timelineCorruptedCoreError.TIMELINE_CORRUPTED'TIMELINE_CORRUPTED'A record of the debug history fails its integrity check or cannot be decoded.
StorageUnavailable7.storageUnavailableCoreError.STORAGE_UNAVAILABLE'STORAGE_UNAVAILABLE'Stored state cannot be read or written.
ClockBeforeEpoch8.clockBeforeEpochCoreError.CLOCK_BEFORE_EPOCH'CLOCK_BEFORE_EPOCH'The device clock reads a time before the Unix epoch.
ValueOutOfRange10.valueOutOfRangeCoreError.VALUE_OUT_OF_RANGE'VALUE_OUT_OF_RANGE'A count or a timestamp does not fit its exported type. The SDK never clamps it.
ArenaFull11.arenaFullCoreError.ARENA_FULL'ARENA_FULL'No more stores can be mounted on this runtime.
Unmounted12.unmountedCoreError.UNMOUNTED'UNMOUNTED'The store is no longer mounted because its runtime was shut down.
InvalidInput13.invalidInputCoreError.INVALID_INPUT'INVALID_INPUT'A value you passed is not valid or cannot be decoded, for example an organization that is not valid.
SourceUnavailable14.sourceUnavailableCoreError.SOURCE_UNAVAILABLE'SOURCE_UNAVAILABLE'The store's last state was computed from inputs that are no longer active and no newer state is ready yet. Reported by a state read (mount, and on the web reading state while no listener is subscribed) and by dispatch while the store's inputs are revoked and no renewed state has been accepted yet; the store stays mounted, and dispatch succeeds again once it has taken the renewed state.
LogsUnavailable15.logsUnavailableCoreError.LOGS_UNAVAILABLE'LOGS_UNAVAILABLE'The SDK's logging could not start or finish: the logging configuration is not valid, or the log journal could not be written when the runtime shut down. Reported by FolioSdk.create, shutdown() and close().

The actions of the session, authentication, vault, Folio document and logs stores wait in one queue of at most 256 actions, shared by all the stores mounted on the runtime. When the queue is full, dispatch throws StoreOverflow. Every action of the inquiry store except the PreviewFrame intent, and every action of the NFC store, skips this queue, so it goes through even when the queue is full. A PreviewFrame that arrives while the queue is full is dropped, and its dispatch does not throw.

SessionStartError

FolioSdk.create fails with it, and SessionUiModel.error carries it when the last sign-out failed. See Session.

CaseFieldsMeaning
Backendstatus, code, messageFolio rejected the session start or refresh. status is the HTTP status; code and message come from Folio.
NetworkmessageFolio could not be reached.
ScopemessageThe services of the new identity could not be started, or the runtime was closed while the session changed.
Coreerror (CoreError)A local failure, such as invalid configuration or unavailable storage.

status is UInt16 in Swift, Int in Kotlin and number in TypeScript.

ImageProcessingError

The error of the image helpers FolioSdk.barcodeImage, FolioSdk.computeMetrics and FolioSdk.rotateImage. The helper throws a failed call error with code InternalError (8) whose message is the text of the case. Every case except EmptyImageData carries a text that describes the failure.

CaseMeaning
InsufficientDatarotateImage: the ARGB data is not exactly width × height × 4 bytes. computeMetrics: the data is shorter than the width, height, format and stride require.
InvalidDimensionsThe width or height is zero or otherwise not valid.
EmptyImageDataThe image holds no pixel data.
InvalidStrideThe stride, the bytes per row, is too small for the width and format.
ProcessingErrorAny other failure, for example an empty barcode value, an unknown barcode type or a value the type cannot encode.

The message is the text of the case alone; no case name or prefix precedes it. For example, barcodeImage with an empty value throws empty barcode value, barcodeImage of an Ean13 barcode with the value abc throws barcode encode failed: IllegalArgumentException - Requested contents should be 12 or 13 digits long, but got 3, and computeMetrics of a 10 × 10 RGBA image with no data throws data length (0) < expected (400) for 10x10 Rgba.

InvalidCalendarValue

The failures of the calendar values. When a part is out of range or the text is not in the accepted format, new and parse throw a failed call error with code InternalError (8) whose message is the text of the case, such as "2026-02-29" is not a calendar date for Date. No call returns the case as a value.

CaseFieldsRaised by
DatetextCalendarDate.new, CalendarDate.parse
MonthtextCalendarMonth.new, CalendarMonth.parse
TimetextClockTime.new, ClockTime.parse
DateTimetextNo call of your app; a date and time text that cannot be decoded
EpochMillismillisInstant.fromEpochMillis for an instant outside the years 0000 to 9999

text is the value that was rejected. For new it is the parts written as ISO 8601 text, such as 2026-02-29. millis is Int64 in Swift, Long in Kotlin and bigint in TypeScript.

AttachmentReadError

The failures of getBytes() on an AttachmentRef, such as a photo of a Folio document. The call throws a failed call error with code InternalError (8) whose message is the text of the case, such as attachment access has expired for Expired. No call returns the case as a value.

CaseFieldsMeaning
ExpiredThe reference no longer grants access: the session that listed it has ended, or access to its record was revoked. Use the reference the store publishes next.
NotFoundThe record or the attachment no longer exists.
ReadFailedmessageThe bytes could not be read from the vault.
InvalidMetadatamessageThe checksum recorded for the file is not valid.
SizeMismatchexpected, actualThe bytes read do not have the recorded size.
ChecksumMismatchThe bytes read do not match the recorded checksum.

expected and actual are sizes in bytes: UInt64 in Swift, Long in Kotlin and bigint in TypeScript.

AuthError

The error of a sign-in. It reaches you in AuthUiModel.flow:

  • A retryable error, while a step waits for input, comes as AwaitingInput with an error. The person can try again on the same step.
  • A terminal error, or a retryable one while no step waits, comes as Failed with an error. The sign-in ended; start it again.

See Authentication.

CaseFieldsMeaningRetryable
WrongPasswordThe password is wrong, or it does not unlock the account key Folio sent for the step.yes
WrongCodeThe one-time or authenticator code is wrong or expired.yes
ExpiredThe sign-in session, challenge, intent or token expired.no
WrongRecoveryCodeThe recovery code is wrong.yes
PasskeyFailedThe passkey operation failed.yes
PasskeyCancelledThe person cancelled the passkey prompt.yes
WeakPasswordThe new password was not accepted.yes
Lockeduntil, optionalToo many attempts; Folio reported when the sign-in unlocks, as until.yes
RateLimitedretryAfter, optionalToo many attempts; wait before the next one.yes
NetworkFolio could not be reached.yes, while a step waits
UnsupportedcapabilityThe device does not support what the step needs, for example "passkey".yes
RecoveryRequiredThe account must be recovered before it can sign in.no
NotPermittedFolio does not allow the operation for this account, device, identifier or credential.no
ServerErrorFolio failed, or rejected the request as invalid.no
TokenPersistFailedThe session tokens could not be saved on the device, or removed from it.no
KeyUnavailableThe device's key storage failed or holds unusable key material.no
SessionUnavailablemessageThe sign-in succeeded but the SDK could not switch the session to the new identity.no
UnknownAny other failure. While a password, code, recovery code or new password step waits, it is reported as that step's wrong-input error instead.yes, while a step waits

until of Locked is a Unix time in seconds: Int64? in Swift, Long? in Kotlin and bigint | undefined in TypeScript. retryAfter of RateLimited is a wait in seconds: UInt64? in Swift, Long? in Kotlin and bigint | undefined in TypeScript.

VaultErrorView

VaultUiModel.error wraps the vault's error with its code:

FieldMeaning
errorCodeThe code of the case: vault. and the case name in lowerCamelCase, such as vault.notFound.
detailsThe VaultError. Match on its case to react to the error.

VaultError

The error of the vault. It reaches you in details of VaultUiModel.error. See Vault and Sharing.

CaseFieldsMeaning
NotFoundmessageThe record was not found.
PermissionDeniedThe account has no permission for the operation.
RevokedAccess to the record was revoked.
PolicyDeniedA policy does not allow the operation.
RevisionConflictmessageThe record changed since it was read.
IdempotencyConflictmessageA repeated request conflicts with an earlier one.
InvalidRequestmessageFolio rejected the request as invalid.
ChallengeFailedmessageThe answer to a sharing challenge is wrong.
InviteExpiredmessageThe invite expired.
InviteNotPendingmessageThe invite is no longer pending.
InviteNotFoundmessageThe invite was not found.
QuotaExceededmessageThe storage quota is used up.
RecordTooLargemessageThe record is too large.
TokenInvalidmessageA token is not valid.
AttachmentNotFoundmessageThe attachment was not found.
UnauthorizedmessageThe request is not authorized.
EmptyUpdatemessageThe update changes nothing.
CodecmessageData could not be encoded or decoded.
CryptomessageAn encryption or decryption step failed.
Apicode, messageAny other error from Folio, with its code.
StoragemessageLocal storage failed.
CustodymessageThe device's key custody failed.
DraftNotFoundhandleThe draft was not found.
InvalidWrappedKeymessageA wrapped key is not valid.
MissingIdentityKeyThe identity key is missing.
UnsupportedRecordTyperecordTypeThe record type is not supported.
OfflineThe device is offline.
OfflineFolderOpNotSupportedFolder operations are not supported while offline.
UpstreamUnavailablemessageA service behind Folio is unavailable.
AttachmentNotUploadedThe attachment was not uploaded.
AttachmentClientIdMismatchThe attachment does not belong to the record.
AttachmentCorruptedrecordClientId, attachmentClientIdThe attachment is corrupted.
TransientNotSupportedThe operation is not supported for a guest session.
EncoderUnavailableformatThe platform has no encoder for this image format.
RecordNotAppliedrecordId, messageA change to the record was not applied.
RecordIdNotReservedrecordIdThe record id is not reserved for this account.
RecordIdMismatchexpected, receivedFolio returned another record id than the one sent.
UnsupportedBodyVersionversionThe record body version is not supported.
UnknownSchemaschemaThe record schema is not registered.
SchemaMismatchrecordId, expected, receivedThe record carries another schema than expected.
InvalidRegistrymessageThe vault registry is not valid.
UnregisteredSchemaschemaNo handler is registered for the schema.
FileTooLargelimitBytesA file is larger than limitBytes bytes.

format of EncoderUnavailable is an ImageFormat. version of UnsupportedBodyVersion and limitBytes of FileTooLarge are UInt32 in Swift, Long in Kotlin and number in TypeScript.

InquiryErrorView

InquiryUiModel.error is not the raw error but its projection for the screen:

FieldMeaning
textOptional. The text to show. When it is empty, show the step's generic error text.
placementField with the field the error belongs to, or Banner.
retryableWhether to offer a retry, which sends the Retry intent.

See Errors in the model for the placement rules.

InquiryError

The error of an inquiry. It reaches you as the raw value in InquiryLifecycle.Failed, and it is the source of InquiryUiModel.error. The placement and retryable columns describe that projection, an InquiryErrorView: where the error is shown, with which text, and whether it offers a retry. A failure of a Resume entry before its first step never offers one. The field of an Otp error is value, the contactField or codeField of the step. A case that says the update is not applied leaves the previous step on screen.

CaseTypeScript typeCodeFieldsMeaningPlacementRetryable
InvalidEntryINVALID_ENTRYinquiry.invalidEntryThe entry has a blank launch code or handoff code, or an inquiry id that is given but blank.Banner, no textno
BootFailedBOOT_FAILEDinquiry.bootFailedmessageThe inquiry runtime failed to start, for example because its files did not load.Banner, no textno
EmbedEMBEDinquiry.embedreason, messageThe embed loader failed. See Embed errors.Banner, no textno
LaunchInvalidLAUNCH_INVALIDinquiry.launchInvalidFolio could not tell who launched the inquiry.Banner, no textno
LaunchCodeInvalidLAUNCH_CODE_INVALIDinquiry.launchCodeInvalidFolio does not accept the launch code: it was already used, has expired or is not valid. A Start that fails with it before its first step shows the launch code notice.Banner, no textno
TokenInvalidTOKEN_INVALIDinquiry.tokenInvalidFolio reported the inquiry's token as not valid.Banner, no textno
TokenExpiredTOKEN_EXPIREDinquiry.tokenExpiredFolio reported the inquiry's token as expired.Banner, no textno
NotStartedNOT_STARTEDinquiry.notStartedThe inquiry has not started.Banner, no textno
NotControllerNOT_CONTROLLERinquiry.notControllerFolio rejected a request because another device controls the inquiry. The store makes this device an observer and reads the inquiry again, so the model shows the observer screen instead. Two requests are the exception: when Folio rejects the request of ContinueHere that takes control, or the read of the result once the inquiry reaches its end, the error reaches the model as a banner. See Control of the inquiry.Banner, no textno
InvalidStateINVALID_STATEinquiry.invalidStateThe inquiry is in a state that does not allow the request. A selfie capture that is incomplete or does not match its state fails the update with it, and the update is not applied. A resumed identity save whose mapper returns a different body, and a government id verification while no session holds a vault, fail the verification with it; the inquiry stays open. See The SDK checks each capture and Identity records.Banner, no textno
AlreadyCompletedALREADY_COMPLETEDinquiry.alreadyCompletedThe inquiry already completed, or already started.Banner, no textno
CompletionIncompleteCOMPLETION_INCOMPLETEinquiry.completionIncompleteThe inquiry cannot complete yet.Banner, no textno
StepNotAvailableSTEP_NOT_AVAILABLEinquiry.stepNotAvailableThere is no current step to act on.Banner, no textno
InvalidStepTypeINVALID_STEP_TYPEinquiry.invalidStepTypeThe intent does not fit the current step.Banner, no textno
RequirementUnresolvableREQUIREMENT_UNRESOLVABLEinquiry.requirementUnresolvableA requirement of the inquiry cannot be met.Banner, no textno
MaxAttemptsMAX_ATTEMPTSinquiry.maxAttemptsThe maximum number of attempts is reached.Banner, no textno
AttemptInProgressATTEMPT_IN_PROGRESSinquiry.attemptInProgressAnother attempt is still running.Banner, no textno
HandoffExpiredHANDOFF_EXPIREDinquiry.handoffExpiredThe handoff code expired.Banner, no textno
HandoffConsumedHANDOFF_CONSUMEDinquiry.handoffConsumedThe handoff code was already used.Banner, no textno
HandoffMismatchHANDOFF_MISMATCHinquiry.handoffMismatchThe handoff belongs to another user or another region.Banner, no textno
SchemaValidationSCHEMA_VALIDATIONinquiry.schemaValidationmessageThe submitted data does not match the step. The banner shows message.Banner with messageno
FieldValidationFIELD_VALIDATIONinquiry.fieldValidationmessageA submitted field is not valid. The banner shows message.Banner with messageno
NotFoundNOT_FOUNDinquiry.notFoundThe inquiry was not found.Banner, no textno
ExpiredEXPIREDinquiry.expiredThe inquiry expired.Banner, no textno
ApiAPIinquiry.apicode, messageAny other error from Folio. code is Folio's error code.Banner, no textonly for error.inquiry.internal_error
OtpOTPinquiry.otpreason, messageAn email or phone code step failed. See OTP reasons.Field at value with message for a reason marked at the field; otherwise Banner, no textno
GovIdGOV_IDinquiry.govIdreason, code, messageA government ID step failed. code is the error code of Folio's verifier, such as error.gov_id_nfc.cached.malformed_jwt, and is absent (nil in Swift, null in Kotlin, undefined in TypeScript) when the SDK raised the error itself. See GovId reasons.Banner, no textno
SelfieSELFIEinquiry.selfiereason, messageA selfie step failed. See Selfie reasons.Banner, no textno
NoActiveInquiryNO_ACTIVE_INQUIRYinquiry.noActiveInquiryThere is no inquiry to act on, for example a same-device resume on a device with no saved inquiry.Banner, no textno
WindowAttestationInvalidWINDOW_ATTESTATION_INVALIDinquiry.windowAttestationInvalidmessageThe signed attestation Folio returns for a launch code could not be verified: it is expired, names another inquiry, is malformed or does not match its claims, its signature does not verify, or Folio's key set has no compatible key for it.Banner, no textno
UploadUPLOADinquiry.uploadmessageA file upload failed.Banner, no textno
NetworkNETWORKinquiry.networkmessageFolio could not be reached.Banner, no textyes
CodecCODECinquiry.codecmessageData could not be encoded or decoded.Banner, no textno
CryptoCRYPTOinquiry.cryptomessageAn encryption step failed.Banner, no textno
StorageSTORAGEinquiry.storagemessageLocal storage failed.Banner, no textno
PlatformPLATFORMinquiry.platformmessageA platform service failed, a camera preview frame has the wrong size, or an Edit does not fit its field: a value type the field does not take, or a phone country outside its options.Banner, no textno
RecordMappingRECORD_MAPPINGinquiry.recordMappingmessageYour IdentityRecordMapper threw, or the SDK could not read an identity image as a picture. Nothing was saved, and the inquiry ends as Failed.Banner, no textno
FileTooLargeFILE_TOO_LARGEinquiry.fileTooLargelimitBytesAn image of the verification result that the SDK attaches to the identity record is larger than limitBytes, 32 MiB. The SDK does not call your IdentityRecordMapper, nothing was saved, and the inquiry ends as Failed.Banner, localized text with the limitno
FileUnreadableFILE_UNREADABLEinquiry.fileUnreadablefieldA picked file could not be read; your UI sent FileUnreadable.Field at field, localized textno
InvalidLinkINVALID_LINKinquiry.invalidLinkurlA link of the step, or the terminal redirect, has a url that does not parse, or the liveness service address of a selfie state does not parse or is not the Folio selfie proxy of the SDK (scheme, origin, path, no user name, query or fragment). The update is not applied.Banner, no textno
LinkRefusedLINK_REFUSEDinquiry.linkRefusedurlThe device refused to open a valid link; your UI sent LinkRefused.Banner, localized textno
MissingCaptureFieldMISSING_CAPTURE_FIELDinquiry.missingCaptureFieldstepA selfie photo step names no field to upload the photo to. step is the step id. The update is not applied.Banner, no textno
MissingFieldLabelMISSING_FIELD_LABELinquiry.missingFieldLabelfieldA field of the step that needs a label has none. The update is not applied.Banner, no textno
InvalidCodeLengthINVALID_CODE_LENGTHinquiry.invalidCodeLengthstep, lengthA one-time code step asks for a code length outside 4 to 8. The update is not applied.Banner, no textno
UnknownCountryUNKNOWN_COUNTRYinquiry.unknownCountryfield, codeA phone field, or the phone of a phone code step, names a country it cannot offer: one without a dial code, or a default country outside its countries. The update is not applied.Banner, no textno
MissingDefaultCountryMISSING_DEFAULT_COUNTRYinquiry.missingDefaultCountryfieldA phone field has no default country. The update is not applied.Banner, no textno
InvalidDateINVALID_DATEinquiry.invalidDatefield, valueThe default, earliest or latest date of a date field is not an ISO date. The update is not applied.Banner, no textno
UnsupportedDateFormatUNSUPPORTED_DATE_FORMATinquiry.unsupportedDateFormatfield, formatA date field has a date format the SDK cannot mask. The update is not applied.Banner, no textno
UnsupportedTimeZoneUNSUPPORTED_TIME_ZONEinquiry.unsupportedTimeZonefield, zoneA date field names a time zone the device does not know. The update is not applied.Banner, no textno
InvalidWeekdayINVALID_WEEKDAYinquiry.invalidWeekdayfield, dayA date field disables a weekday outside 0 (Sunday) to 6 (Saturday). The update is not applied.Banner, no textno
MissingDateFieldOffsetMISSING_DATE_FIELD_OFFSETinquiry.missingDateFieldOffsetfieldA date field that checks against today has no resolved UTC offset. The edit is not applied.Banner, no textno
LocaleNotSavedLOCALE_NOT_SAVEDinquiry.localeNotSavedmessageThe language choice could not be saved; nothing was sent to Folio.Banner, no textyes

length of InvalidCodeLength and day of InvalidWeekday are Int64 in Swift, Long in Kotlin and bigint in TypeScript. limitBytes of FileTooLarge is UInt32 in Swift, Long in Kotlin and number in TypeScript. code of GovId is optional: String? in Swift and Kotlin, string | undefined in TypeScript. In Swift the case is .govId(reason:code:message:).

The code names the error in the SDK's debug log: a failed inquiry request is logged as the warning inquiry effect failed with the code in error_code, for example inquiry.tokenExpired. See Logging.

OTP reasons

OtpErrorReason, the reason of an Otp error. The reasons marked "at the field" are shown at the step's value field with the message from Folio: the contact field (contactField) while the email address or phone number is entered, and the code field (codeField) while the code is entered. InvalidTarget, MissingTarget and DeliveryFailed concern the contact. The others are banners without text.

When RecoveryRequired comes back while the SDK runs a verification command of the step, the SDK reports the command to Folio as rejected instead of showing the error, and Folio decides how the step goes on. The same holds for the selfie reason RecoveryRequired.

ReasonMeaningShown
RecoveryRequiredFolio holds no verification session for the step any more, for example a code confirmed before one was sent.banner
InvalidCodeThe code is wrong.at the field
ExpiredCodeThe code expired.at the field
AttemptsExhaustedNo attempts are left.at the field
ConfirmExhaustedNo confirmation attempts are left.at the field
InvalidTargetThe email address or phone number is not valid.at the field
MissingTargetThe email address or phone number is missing.at the field
DeliveryFailedThe code could not be delivered.at the field
StepInactiveThe step is no longer active.banner
NotFoundThe verification was not found.banner
IdempotencyConflictA repeated request conflicts with an earlier one.banner
ForbiddenThe request is not allowed.banner
ConfigInvalidThe step's configuration is not valid.banner
SystemThe verification service failed.banner
OtherAny other reason.banner

GovId reasons

GovIdErrorReason, the reason of a GovId error. It covers the document photo check, the NFC chip check and the face match. A Cached reason concerns a verification result saved earlier that the inquiry presented again instead of a new capture.

ReasonMeaning
DocCountryDisallowedDocuments of this country are not accepted.
DocExpiredThe document expired.
DocElectronicReplicaThe capture shows an electronic replica, not the physical document.
DocTamperingDetectedThe document shows signs of tampering.
DocMrzChecksumFailedA check digit of the machine readable zone is wrong.
DocRecognizeFailedThe document could not be recognized.
NfcUnsupportedThe chip data needed for the step is not available.
NfcPaFailedPassive authentication of the chip data failed.
NfcChainFailedThe certificate chain of the chip could not be verified.
NfcRevokedA certificate of the chip was revoked.
NfcNonConformantThe chip data does not conform to the standard.
NfcDataIntegrityFailedThe integrity check of the chip data failed.
NfcDataValidityFailedThe validity check of the chip data failed.
NfcDg1MissingThe chip data has no DG1.
FaceNoMatchThe faces do not match.
FaceEngineUnavailableThe face matching service is not available.
FaceEngineUnavailableTransientThe face matching service is not available right now.
FaceMatchFailedThe face match could not be performed.
ChecksFailedThe document checks failed.
CachedPathEngineBlockedA saved result cannot be used for this step.
CachedMalformedJwtThe saved result is malformed.
CachedInvalidSignatureThe signature of the saved result is not valid.
CachedWrongIssuerThe saved result comes from another issuer.
CachedSubjectMismatchThe saved result belongs to another subject.
CachedExpiredThe saved result expired.
CachedArtifactMismatchThe files of the saved result do not match it.
CachedSchemaIncompatibleThe saved result has an incompatible format.
CachedMissingCheckThe saved result lacks a required check.
CachedPolicyOutdatedThe saved result was made under an outdated policy.
CachedStaleThe saved result is too old.
CachedNonPassResultThe saved result is not a pass.
CachedVerifierDecommissionedThe verifier of the saved result is no longer in service.
ConflictingContextsThe request conflicts with the context of the step.
AttemptsExhaustedNo attempts are left.
StepInactiveThe step is no longer active.
NotFoundThe verification was not found.
AlreadyCompletedThe verification already completed.
RateLimitedToo many requests.
ProcessingUnavailableThe document processing service is not available.
ProcessingInProgressThe document processing is still running.
ProcessingTransactionNotFoundThe document processing transaction was not found.
ConfigInvalidThe step's configuration is not valid.
IdempotencyConflictA repeated request conflicts with an earlier one.
ForbiddenThe request is not allowed.
ReportFailedThe verification report could not be produced.
SystemThe verification service failed.
OtherAny other reason.

Selfie reasons

SelfieErrorReason, the reason of a Selfie error.

ReasonMeaning
CapturedImageMissingThe selfie photo was not uploaded before the step was completed.
CapturedImageInvalidThe uploaded selfie photo is not a valid image: its encoding, size, content type or file signature failed the check.
CapturedImageNotAllowedThe step takes no uploaded photo, because it runs a liveness check.
ProxyDisabledInMockThe liveness service was called for a step that runs in mock mode.
ProxySessionMismatchThe traffic to the liveness service does not match the step's capture session.
AgeOutOfRangeThe estimated age is outside the allowed range.
FaceCoveringDetectedThe face is covered.
GlassesViolationThe glasses rule of the step is violated.
ImageQualityFailedThe image quality check failed.
PortraitQualityFailedThe portrait quality check failed.
PortraitMissingThe liveness check returned no portrait.
DetectFailedThe face detection service failed.
RecoveryRequiredFolio holds no capture session for the step any more.
LivenessFailedThe liveness check failed.
FaceNoMatchThe selfie does not match the document photo.
FaceMatchFailedThe face match could not be performed.
FaceEngineUnavailableThe face matching service is not available.
FaceEngineUnavailableTransientThe face matching service is not available right now.
ChecksFailedThe selfie checks failed.
AttemptsExhaustedNo attempts are left.
StepInactiveThe step is no longer active.
NotFoundThe verification was not found.
AlreadyCompletedThe verification already completed.
LivenessUnavailableThe liveness service is not available.
LivenessInProgressThe liveness check is still running.
LivenessSessionExpiredThe liveness session expired.
LivenessTransactionNotFoundThe liveness transaction was not found.
ConfigInvalidThe step's configuration is not valid.
IdempotencyConflictA repeated request conflicts with an earlier one.
ForbiddenThe request is not allowed.
ReportFailedThe verification report could not be produced.
SystemThe verification service failed.
OtherAny other reason.

Embed errors

The embed loader reports its own failures through onLifecycle as a FAILED lifecycle whose error is an InquiryError. See Inquiry embed.

error.typereason.typeMeaning
EMBEDINVALID_OPTIONSThe mount options are not valid: an empty app.version or app.build, an entry that is not an InquiryEntry, a missing or blank backdrop.color, panel.background or panel.shadow, a container that is not found, no baseUrl to use, or an allowedOrigin that is '*' or cannot be derived. message names the problem.
EMBEDREADY_TIMEOUTThe iframe did not report READY within 15 seconds after it was added.
EMBEDORIGIN_REJECTEDA message came from another origin or window than the one the loader trusts.
EMBEDVERSION_MISMATCHA loader pinned to a major version got a runtime of another major version, or one that reports no version. Load the loader of the matching major version.
BOOT_FAILEDThe runtime or its WASM failed to load.

EmbedFailure, the reason of Embed, has the cases InvalidOptions, ReadyTimeout, OriginRejected and VersionMismatch. In TypeScript the fields sit under value, for example lifecycle.value.error.value.reason.type.

MrtdUiError

The error of an NFC chip read, in MrtdUiModel.error. Every case has a message, the text to show in the runtime's current locale, which the SDK chooses for the cause. See NFC chip reading for the text of each cause.

CaseSwiftTypeScript typeMeaning
InvalidMrz.invalidMrz(message:)INVALID_MRZThe document number, date of birth or date of expiry is not valid.
ConnectionLost.connectionLost(message:)CONNECTION_LOSTThe connection to the chip broke, or the NFC session was cancelled, not found or not available.
Authentication.authentication(message:)AUTHENTICATIONThe chip refused access or an authentication step with the chip failed.
ChipNotSupported.chipNotSupported(message:)CHIP_NOT_SUPPORTEDThe device has no NFC reader or the SDK has no NFC access on the platform, which is always the case in a browser; or the chip does not support the read.
ReadFailed.readFailed(message:)READ_FAILEDNFC is switched off on the device; or a file of the chip could not be read or parsed, or the platform refused the NFC session. An optional data group that the chip reports as absent is skipped instead.
Internal.internal(message:)INTERNALAny other failure.

IdentityMappingError

The failure of your IdentityRecordMapper. IdentityMappingError is a value with one field, message: a struct in Swift, a data class in Kotlin and an interface in TypeScript.

To report a failure, throw from map: any Error on iOS and the web, any exception on Android. The SDK turns what you throw into an IdentityMappingError with its message. On the web the message is the error's message. On iOS it is message of a thrown FolioSDKError; otherwise it is errorDescription of a LocalizedError when that is set, and String(describing:) of the error otherwise. The mapper runs before any write, so the SDK then saves nothing, and the inquiry ends with InquiryLifecycle.Failed and the InquiryError RecordMapping with that message. See Identity records.

On this page