Skip to main content

Troubleshooting and SDK errors (React Native)

This page covers errors from both of our React Native SDKs. The first sections describe the Components SDK (@weavr-io/secure-components-react-native), which wraps the native iOS and Android components SDKs and returns a uniform Result shape. The final section covers the Push ProvisioningPush ProvisioningA method that allows cardholders to add their card to a digital wallet (such as Apple Pay or Google Pay) directly from your app. The card details are securely tokenized and sent to the wallet provider, streamlining the process and enhancing the user experience compared to manual provisioning. This feature is currently in beta. SDK (@weavr-io/push-provisioning-react-native).

For the complete list of underlying native error codes, refer to the iOS and Android error references.

Before you start: Expo Modules runtime

Our SDK is built as an Expo Module, which means it requires the Expo Modules runtime. This applies equally to bare React Native projects and managed Expo workflows. If the runtime is missing or incompletely wired up, you'll see one of these build errors before any of the runtime errors that follow appear:

  • iOS: No such module 'ExpoModulesCore'
  • Android: project :expo-modules-core not found

If you encounter either, revisit the Install Expo Modules step on the get-started page. You don't need to migrate your app to Expo - Expo officially supports installing the Expo Modules runtime into an existing bare React Native app.

Error shape

Async methods return a Result<T, WeavrError> rather than rejecting. The WeavrError carries a string code, a message, and an optional localized message:

export interface WeavrError {
code: string;
message: string;
localizedMessage?: string;
}

The Result type discriminates on error:

const { value, error } = await initializeUXComponents(env, WEAVR_UI_KEY);

if (error) {
console.log(error.code, error.message);
return;
}

// Success - `value` is the typed result.

The known top-level codes are exposed as the ErrorCodes enum:

CodeDescription
UnknownAn unclassified error. Inspect message for the underlying reason.
MissingDataThe native module returned no data and no error. Usually indicates a transport-layer bug.
LoginAlreadyInProgressA biometric login is already running. Wait for it to complete before starting another.

For HTTP-driven failures, code carries the server status code (for example, "401", "403", "5xx"). For SDK-level failures, code carries the underlying native WeavrErrorCode (for example, "1001" for cantSetUIKey). See the iOS and Android pages for the full integer reference.

Initialize components

initializeUXComponents resolves to Result<UXComponentsStatus, WeavrError>. Common failures map to these underlying native codes:

CodeDescription
1001The UI keyUI keyA public key that authorizes Weavr's Secure UI components - the inputs and displays in our Web, Android, iOS, and React Native SDKs that handle passwords, PINs, card details, and KYC/KYB flows. Unlike the API key, the UI key isn't an API credential; you don't call REST endpoints with it. It's safe to embed in client-side code, and Sandbox and Live each have their own UI key. is missing or could not be set.
1002The secure field length could not be fetched or is not available.
1003The device key pair could not be created or restored.
1004The biometric security service could not be initialized.
1005The server public key could not be retrieved.

initializePSA runs synchronously and assumes initializeUXComponents succeeded first. If the underlying native call throws, the exception propagates to your caller - wrap it in a try/catch if you need to handle it.

Set user token

setUserToken resolves to Result<string, WeavrError>. The error's code is one of:

  • An HTTP status code from the token validation or association API call.
  • An SDK-level code (typically "1001") for local precondition failures such as a missing UI keyUI keyA public key that authorizes Weavr's Secure UI components - the inputs and displays in our Web, Android, iOS, and React Native SDKs that handle passwords, PINs, card details, and KYC/KYB flows. Unlike the API key, the UI key isn't an API credential; you don't call REST endpoints with it. It's safe to embed in client-side code, and Sandbox and Live each have their own UI key..

Common HTTP status codes

CodeDescription
400Bad request.
401Unauthorized.
403Forbidden.
404Not found.
409Conflict.
412Precondition failed.
429Too many requests.
5xxServer error (500, 502, 503, 504, and others).

Update FCM token

updateFCMToken resolves to Result<boolean, WeavrError>. Failures use the same code conventions as setUserToken: an HTTP status code from the device-token API call, or "1001" if the UI keyUI keyA public key that authorizes Weavr's Secure UI components - the inputs and displays in our Web, Android, iOS, and React Native SDKs that handle passwords, PINs, card details, and KYC/KYB flows. Unlike the API key, the UI key isn't an API credential; you don't call REST endpoints with it. It's safe to embed in client-side code, and Sandbox and Live each have their own UI key. is missing.

Tokenize secure fields

createTokens resolves to Result<CreateTokenResponse, WeavrError>. Failures use:

CodeDescription
1001The UI keyUI keyA public key that authorizes Weavr's Secure UI components - the inputs and displays in our Web, Android, iOS, and React Native SDKs that handle passwords, PINs, card details, and KYC/KYB flows. Unlike the API key, the UI key isn't an API credential; you don't call REST endpoints with it. It's safe to embed in client-side code, and Sandbox and Live each have their own UI key. is missing.
1002The passcode length has not been fetched, or the input length doesn't match the requirement.
-1A runtime exception occurred during tokenizationTokenizeReplace a card's primary account number (PAN) with a unique digital token that stands in for the real card during a transaction. When a cardholder adds a card to Apple Pay or Google Pay via push provisioning, the wallet provider stores a device-specific token rather than the underlying PAN, so the real card number isn't exposed on the device or shared with merchants..
HTTPServer error during the tokenizationTokenizeReplace a card's primary account number (PAN) with a unique digital token that stands in for the real card during a transaction. When a cardholder adds a card to Apple Pay or Google Pay via push provisioning, the wallet provider stores a device-specific token rather than the underlying PAN, so the real card number isn't exposed on the device or shared with merchants. API call.

Start biometric enrollment

startEnrollment resolves to a BiometricsEnrollmentResult discriminated union - not a Result. Branch on the case field:

CaseDescription
completedThe enrollment flow completed successfully.
initialisationErrorThe SDK was not properly initialized when enrollment was triggered. The error field describes what went wrong.
cryptographyErrorAn error occurred in the cryptography module. The error field describes the cause.
failedBiometricsChallengeThe user failed the biometrics challenge.
unauthorizedThe token is not authorized. Sign the user in again and provide a new token.
userDoesNotConsentThe user dismissed the consent screen without confirming.
failedToLoadBrandThe flow could not launch because the biometrics configuration couldn't be fetched.
noPhoneNumberAvailableThe user has no associated phone number.
noBiometricsAvailableBiometrics are not available. The biometricAvailability field is noHardware, hwUnavailable, or noneEnrolled.
challengeFailedThe enrollment challenge failed (for example, the OTP expired). The cause field carries the reason.
const result = await startEnrollment();

switch (result.case) {
case "completed":
// Enrolled.
break;
case "noBiometricsAvailable":
if (result.biometricAvailability === "noneEnrolled") {
// Prompt the user to enroll a fingerprint or face in system settings.
}
break;
case "challengeFailed":
console.log(result.cause);
break;
// ...
}

Start biometric login

startBiometricLogin resolves to Result<WeavrSecureLoginData, WeavrError>. The error's code is one of:

  • An HTTP status code from the login, verification, or password-fallback API call.
  • An SDK-level code for local precondition failures.

SDK-level error codes

CodeDescription
1001The UI keyUI keyA public key that authorizes Weavr's Secure UI components - the inputs and displays in our Web, Android, iOS, and React Native SDKs that handle passwords, PINs, card details, and KYC/KYB flows. Unlike the API key, the UI key isn't an API credential; you don't call REST endpoints with it. It's safe to embed in client-side code, and Sandbox and Live each have their own UI key. is missing.
1003No enrollment key is on the device. Call startEnrollment first.
1005The server public key required for password fallback could not be retrieved.
2001The Play Integrity token, challenge ID, nonce, or initial login response is invalid.
-1Local biometric authentication failed, the prompt was canceled, or another local error occurred.

Troubleshooting Invalid Origin (HTTP 403)

On Android, all HTTP 403 responses are mapped to Invalid Origin. The first call to surface this is usually login, but the underlying cause is shared across the SDK. See Troubleshooting ENROLLMENT_FAILED: Invalid Origin on the Android page for the full root-cause matrix (Play Integrity setup, GCP project linking, environment-key mismatch, sideloaded builds).

Start biometric SCA challenge

startChallenge resolves to Result<WeavrChallengeResult, WeavrError>. The error's code is one of:

CodeDescription
1001The UI keyUI keyA public key that authorizes Weavr's Secure UI components - the inputs and displays in our Web, Android, iOS, and React Native SDKs that handle passwords, PINs, card details, and KYC/KYB flows. Unlike the API key, the UI key isn't an API credential; you don't call REST endpoints with it. It's safe to embed in client-side code, and Sandbox and Live each have their own UI key. is missing.
1003The enrollment key is missing.
2001The challenge ID or nonce is missing.
-1The server returned an empty response, or a local exception occurred.
HTTPServer error during challenge retrieval or verification.

Decline operations follow the same code conventions as verify.

Start KYC flow

KYCKYC (Know Your Customer). Know Your Customer - the identity verification process for consumer customers. This process allows you to securely verify your user's identity. Weavr asks users to submit the information and documentation they need for approval by financial providers. errors are reported through the KYCErrorType enum. Listen via the KYCKYC (Know Your Customer). Know Your Customer - the identity verification process for consumer customers. This process allows you to securely verify your user's identity. Weavr asks users to submit the information and documentation they need for approval by financial providers. SDK callbacks on the component:

TypeDescription
UnknownAn unexpected error occurred.
InvalidParametersInvalid parameters were provided to the KYCKYC (Know Your Customer). Know Your Customer - the identity verification process for consumer customers. This process allows you to securely verify your user's identity. Weavr asks users to submit the information and documentation they need for approval by financial providers. flow.
UnauthorizedThe user is not authorized; the token is invalid or expired.
InitialLoadingFailedInitial loading of the KYCKYC (Know Your Customer). Know Your Customer - the identity verification process for consumer customers. This process allows you to securely verify your user's identity. Weavr asks users to submit the information and documentation they need for approval by financial providers. flow failed.
ApplicantNotFoundThe KYCKYC (Know Your Customer). Know Your Customer - the identity verification process for consumer customers. This process allows you to securely verify your user's identity. Weavr asks users to submit the information and documentation they need for approval by financial providers. applicant could not be found.
ApplicantMisconfiguredThe KYCKYC (Know Your Customer). Know Your Customer - the identity verification process for consumer customers. This process allows you to securely verify your user's identity. Weavr asks users to submit the information and documentation they need for approval by financial providers. applicant is misconfigured in our system.
NetworkErrorA network error occurred during the KYCKYC (Know Your Customer). Know Your Customer - the identity verification process for consumer customers. This process allows you to securely verify your user's identity. Weavr asks users to submit the information and documentation they need for approval by financial providers. process.
UnexpectedErrorAn unexpected error occurred that doesn't fit other categories.
InititlizationErrorKYCKYC (Know Your Customer). Know Your Customer - the identity verification process for consumer customers. This process allows you to securely verify your user's identity. Weavr asks users to submit the information and documentation they need for approval by financial providers. initialization failed.

Push provisioning SDK

Our push-provisioning SDK (@weavr-io/push-provisioning-react-native) wraps the native iOS (Apple Wallet) and Android (Google Wallet) provisioning SDKs. This section documents the unified error shape, the cross-platform error codes, and where to look for platform-specific detail.

Push provisioning error shape

AddToWalletButton reports the outcome through its onComplete prop. On failure, error is a WeavrError; on success, error is null and value carries the result:

export type ErrorCode = "Failed" | "Canceled" | "Unknown";

export interface WeavrError<T = ErrorCode> {
code: T;
message: string;
weavrErrorCode?: string;
}
FieldDescription
codeA high-level classifier: Failed (the SDK couldn't complete the flow), Canceled (the user backed out), or Unknown.
messageA human-readable description of the failure.
weavrErrorCodeThe underlying native error code (for example, CARD_NOT_ELIGIBLE). Use this to branch on specific scenarios.
<AddToWalletButton
// …
onComplete={({ error, value }) => {
if (error) {
switch (error.weavrErrorCode) {
case "CARD_NOT_ELIGIBLE":
// Surface to the user; escalate to the issuer if needed.
break;
case "NETWORK_ERROR":
// Retry with backoff.
break;
default:
console.error(error.code, error.message);
}
return;
}
// Success.
}}
/>

getCardStatusInWallet and isGooglePayAvailable reject with the same WeavrError shape - handle them via .catch() or try/await.

Push provisioning error codes

The following codes can appear in error.weavrErrorCode. Some codes are platform-specific because Apple Wallet and Google Wallet expose different failure modes:

CodePlatformScenarioRecommended action
SDK_NOT_INITIALISEDBothInitialization missingInitialize the SDK before any provisioning call.
CARD_NOT_PROVISIONEDBothSet-default attempted on an unknown cardPrompt the user to add the card first.
NETWORK_ERRORBothConnectivity issueRetry with backoff; surface an offline state.
CARD_NOT_ELIGIBLEBothThe backend flagged the card as ineligibleShow a user-friendly message; escalate to the issuer.
COULD_NOT_FETCH_PROVIDERBothMissing routing data from the backendValidate the backend response and provisioning configuration.
UNAUTHORIZEDBothToken missing or rejectedRefresh the authentication token.
MISSING_* (2001–2007)BothAddToWalletButton missing parametersEnsure all required props are set before the user taps.
SETUP_ERRORBothLocal app misconfigurationRevisit the installation steps; check manifest metadata (Android) or bundle configuration (iOS).
UNKNOWN_ERRORBothUnmapped exceptionCapture logs and contact our support team.
GOOGLE_PAY_PROVISIONING_PAYLOAD_ERRORAndroidGoogle Pay SDK payload errorValidate the card data and retry.
INSECURE_DEVICE_ERRORAndroidDevice not secure (debugging or rooted)Inform the user; provisioning is blocked on insecure devices.
CLIENT_NOT_AVAILABLE_ERRORAndroidGoogle Pay client unavailablePrompt the user to update Google Play Services.
GOOGLE_PAY_ERRORAndroidGoogle Pay SDK general errorCheck device compatibility and Google Play Services.
GOOGLE_PAY_TOKEN_ALREADY_EXISTSAndroidThe card is already provisionedUpdate the UI to reflect the provisioned state.
GOOGLE_PAY_TOKEN_NOT_FOUNDAndroidToken not found in Google PayRetry the card-status check or prompt re-provisioning.
INVALID_ACTIVITYAndroidHost is a non-FragmentActivityUse AppCompatActivity, or attach the fragment correctly.
Google Pay codes are Android-only

The 3000-series Google Pay codes are Android-only. Apple Wallet has its own error surface - see the iOS push-provisioning troubleshooting page for the underlying iOS-specific codes (for example, cantBeAddedToAppleWallet, cantObtainPaymentPassRequestConfiguration).

Installation and build issues

The following issues aren't SDK errors returned at runtime - they show up during installation or at build/launch time.

Xcode 26 iOS build failure

Symptom: iOS builds fail on Xcode 26 with errors deep inside the fmt Pod - the C++ formatting library that React Native pulls in transitively. Errors reference consteval or FMT_USE_CONSTEVAL and don't point at any of your own code.

Cause: Xcode 26's Clang advertises support for consteval via __cpp_consteval, so fmt flips FMT_USE_CONSTEVAL to 1 and takes a code path that the new compiler can't actually compile. This isn't specific to our SDK - it affects any React Native or Expo iOS build on Xcode 26 until fmt ships an upstream fix. Tracking: expo/expo#44229.

Fix: patch fmt/include/fmt/base.h from your Podfile so FMT_USE_CONSTEVAL is forced back to 0. Patching from post_install keeps the workaround in place across pod install re-runs without you editing Pod sources by hand. Add (or extend) the post_install block in ios/Podfile:

ios/Podfile
post_install do |installer|
# Xcode 26 workaround: patch fmt to disable consteval.
fmt_base = File.join(installer.sandbox.root, 'fmt', 'include', 'fmt', 'base.h')
if File.exist?(fmt_base)
content = File.read(fmt_base)
unless content.include?('Xcode 26 workaround')
patched = content.gsub(
/^(#elif defined\(__cpp_consteval\)\n# define FMT_USE_CONSTEVAL) 1/,
"// Xcode 26 workaround: disable consteval\n\\1 0"
)
if patched != content
File.chmod(0644, fmt_base)
File.write(fmt_base, patched)
end
end
end
end

Then re-run pod install from ios/ and rebuild. consteval is a compile-time optimization; flipping it to 0 makes fmt fall back to constexpr with no runtime impact.

This is a workaround - once fmt releases an upstream fix and Expo or React Native picks it up, drop the patch and update the Pod. If you can't apply the patch, downgrading to Xcode 15 also resolves it. For a longer walk-through of the same fix, see "Xcode 26.4 Just Broke Your React Native Build".

App crashes at launch with "Library not loaded" for a Weavr framework

Symptom: the app builds and links without errors, but crashes immediately on launch (before any of your JavaScript runs) with a dyld error such as:

dyld[...]: Library not loaded: @rpath/WeavrComponents.framework/WeavrComponents
Referenced from: <...> /YourApp.app/YourApp
Reason: tried: '.../YourApp.app/Frameworks/WeavrComponents.framework/WeavrComponents' (no such file)

The same failure can occur for WeavrPushProvisioning.framework. This typically shows up on projects that also ship an app extension (for example, the Wallet Extension used by push provisioning) that statically links one of our frameworks which your main app target also depends on.

Cause: our underlying iOS frameworks use Apple's mergeable libraries feature (MERGEABLE_LIBRARY = YES) so they can be statically linked into an app extension. For WeavrComponents, this also avoids a SwiftUICore linker error that occurred because it depends on SwiftUI; WeavrPushProvisioning has no SwiftUI dependency, so that error doesn't apply to it. A side effect of adopting mergeable libraries is that the framework's binary carries a newer Mach-O load command (LC_ATOM_INFO) that CocoaPods uses ruby-macho to inspect when deciding whether a vendored xcframework needs to be embedded in a given target. CocoaPods versions that bundle ruby-macho older than 4.1.0 (this includes CocoaPods 1.16.x and earlier) can't parse that load command, silently treat the framework as static, and skip generating the "Embed Pods Frameworks" step for it - even for your main app target, and even though the framework is still linked. The framework compiles and links fine; it's just never copied into the app bundle, so dyld can't find it at runtime.

Fix: pin a CocoaPods version whose ruby-macho dependency understands LC_ATOM_INFO (CocoaPods 1.17.0+, which depends on ruby-macho ~> 4.1.0). Add a Gemfile at your project root if you don't already have one:

Gemfile
source 'https://rubygems.org'

gem 'cocoapods', '>= 1.17.0'

Then install and use it explicitly:

bundle install
cd ios && bundle exec pod install

If you already run pod install through Bundler (a Gemfile and Gemfile.lock are the standard way CocoaPods versions are pinned for a React Native project), just bump the cocoapods version and re-run bundle install. Running a bare pod install against a global CocoaPods gem older than 1.17.0 reproduces the issue even if your Gemfile is correct, so make sure CI and every developer machine call pod install through bundle exec.

See also