Code
21
SDK error · code 21
What it means
invalidSubscriberAttributesError (code 21) means the server could not save one or more customer attributes, reported as backend code 7263 or 7264. The error lists the failing keys. Fix or drop those values, for example an invalid $email. The valid attributes in the same request are still saved, and the error never blocks a purchase.
Code
21
iOS (Swift)
ErrorCode.invalid
Android (Kotlin)
PurchasesErrorCode.Invalid
Causes
$, has a bad value, for example an email address that is not an email.attribute_errors entry in userInfo (ErrorDetails.swift).| Backend code | Meaning |
|---|---|
| 7263 | Invalid subscriber attributes: one or more attributes could not be saved. |
| 7264 | Invalid subscriber attributes body. |
Fix
On iOS read attribute_errors from userInfo, or subscriberAttributesErrors on the public error. It maps each failing key to a message.
Check that $email looks like an email address, and trim values, before you call setEmail or setAttributes.
Remove the failing key, or send a valid value. The next sync posts the corrected attributes.
Attribute sync runs in the background. Log the failing keys and carry on.
In your app
$) counts as a blocking error for the combined attributes-and-offerings sync, but a failure for a reserved $ key does not (Purchases.swift). Do not grant or withhold access based on it.// Swift
do {
let result = try await Purchases.shared.purchase(package: package)
} catch let error as ErrorCode where error == .invalidSubscriberAttributesError {
// handle invalid subscriber attributes
}
// Kotlin
if (error.code == PurchasesErrorCode.InvalidSubscriberAttributesError) { /* ... */ } On RevenueDot: RevenueDot validates $email. If it is not an email address, it answers HTTP 400 with code 7263, lists the key in attribute_errors, and still saves every other attribute in the request.
FAQ
It checks $email and answers 400 with code 7263 when the value is not an email address. It saves the other attributes in the same request and lists the rejected key in attribute_errors.
No. Attributes sync separately from purchases. A failed attribute does not block a purchase or an entitlement.
In React Native, compare error.code with PURCHASES_ERROR_CODE.INVALID_SUBSCRIBER_ATTRIBUTES_ERROR. In Flutter, convert the PlatformException with PurchasesErrorHelper.getErrorCode(e) and compare the result with PurchasesErrorCode.invalidSubscriberAttributesError.
Get started
RevenueDot answers the same SDK calls with the same error codes. Start free on RevenueDot Cloud, free up to $10,000 a month in tracked revenue.
Already have an account? Sign in · Prefer your own servers? Self-host free