Troubleshooting¶
getClassification() never returns .human¶
Cause: One of the following:
- The user has not consented, so nothing is recorded.
- The session has fewer actions than the model asks for, 8 with the built-in model: the result
is
.insufficient. See Evidence. - Capture was paused and never resumed.
start()was never called.- The SDK cannot score:
readyisfalseand the result is.insufficient. - The score is between the model's two thresholds, which gives
.undeterminedby design.
Solution: Check each in turn:
import DeaBase
import DeaSDK
if let dea = Dea.sdk {
print("consent:", dea.consent.decision) // must be granted
print("ready:", dea.ready) // must be true
print("fault:", dea.coreFault ?? "none") // must be none
print("processed:", dea.coreCounts.samples) // must grow as you touch
// the result leaves `.insufficient` at 8 actions with the built-in model:
print("score:", String(describing: try? dea.getClassification()))
}
Make sure every pause() has a matching resume().
getClassification() throws ThresholdMissing¶
Cause: The loaded scoring model carries no bot threshold, so no reading can be classified. Every
model DEA ships carries one, the built-in model included; modelVersion on the error names the
model that does not.
Solution: Report the modelVersion to DEA. Until a model with thresholds is installed, treat
the thrown error as .undetermined.
ready is false¶
Cause: The scoring engine bundled with DeaSDK could not be loaded. coreFault says why:
coreFault |
Meaning |
|---|---|
no core binary in this build |
The build has no scoring engine for its platform |
core ABI …, this adapter speaks … |
The scoring engine in the build comes from a different release than DeaSDK |
core built for profile …, wanted 0 |
The build carries the scoring engine meant for desktop browsers |
Solution: Build for an iOS device or the iOS Simulator. Make sure DeaSDK, DeaBase and the
scoring engine bundled with DeaSDK come from the same release, then clean the build folder
(Product → Clean Build Folder).
Nothing is processed when touching the screen¶
Cause: Nothing is being recorded. Usually the user has not consented yet; otherwise capture is
paused, start() was never called, or the instance was disposed.
Solution: Show the consent alert and accept it — see
User Consent. Then check that start() runs at launch
and that every pause() has a matching resume().
The consent alert appears on every launch¶
Cause: The answer is not being stored, or your code asks without checking. Either
remember: false is passed, consent is set to a Consent over a MemoryConsentStore, or a
SwiftUI deaConsent alert is shown without checking consent.isAnswered first.
Solution: Remove remember: false unless the device is shared. In SwiftUI, set the asking
binding only when consent.isAnswered is false:
captureEvent returns false¶
Cause: The name is empty or longer than 64 characters, the data is larger than 1024 bytes as JSON, or nothing is being recorded (no consent, paused, or disposed).
Solution: Shorten the name or the data. The iOS SDK refuses an over-long name rather than shortening it. See Custom Events.
captureKey records nothing¶
Cause: .keyDown is not in the events option (or .keyUp, for a call with
pressed: false), or nothing is being recorded (no consent, paused, or disposed).
Solution: Add the key kinds to events. See
Report typing.
The app freezes when calling attest()¶
Cause: attest() and renewAttestation() make network requests and block the calling thread
until they finish. Called on the main thread, they freeze the UI.
Solution: Call them from a background queue or a detached task:
attest() returns unsupported¶
Cause: One of the following:
- No
appKeywas given.detailsays so, and no request was made. - No signing key could be created: the device refused to create a key in the Secure Enclave or
the keychain.
detailisnil.
Solution: Pass the appKey DEA issued for this app — see
Options. If an appKey is set, test on another device. On the
simulator, the SDK falls back to a software key, so unsupported there points to a keychain problem
in the build (for example a missing keychain entitlement in a test host).
attest() passes but platformAttested is false¶
Cause: The key was registered without an App Attest token. This is expected on the iOS Simulator, on devices older than iOS 14 and on devices without App Attest. It also happens when App Attest does not answer within 15 seconds.
Solution: Test on a real device running iOS 14 or later. A device that supports App Attest gets
a token on the next registration — renewAttestation() registers again now.
attest() returns failed¶
Cause: DEA refused the registration, DEA could not be reached, or App Attest refused.
Solution: Read attestation.detail:
detail contains |
Meaning |
|---|---|
invalidKey |
App Attest refused the key. The App Attest entitlement is usually missing from the build — see Attest |
/api/attest/challenge answered 401 |
DEA does not recognise the appKey |
/api/attest answered 403 |
DEA refused the registration |
unreachable |
No answer from DEA: no network, or a timeout |
attestation paused until |
DEA refused earlier registrations that used App Attest, and the SDK is waiting before it tries again. forgetAttestation() ends the wait |