fix(android): return stable error codes instead of localized messages#110
fix(android): return stable error codes instead of localized messages#110alvistar wants to merge 2 commits into
Conversation
`handleRegistrationException` / `handleAuthenticationException` fall through to `e.errorMessage.toString()`, which is human-readable display text and cannot be branched on. Return the androidx `type` constant instead, and map `CreateCredentialNoCreateOptionException` to a dedicated `NoCreateOption` code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fails without the mapping (the rejection surfaces as `{error: 'Native error'}`),
passes with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Added a deterministic regression test in It reproduces the bug at the JS seam — a native rejection with So the test is red on The native half ( |
|
On-device confirmation of the native half, now that the patched module is compiled in Repro: remove the Google account from the device, then call Before (upstream After (this PR): The stable code reaches JS, so the app can branch on it. In our case that turns a dead-end |
Problem
Both Android exception handlers fall through to the localized message:
errorMessageis human-readable display text, so anything not explicitly mappedreaches JS as an unmatchable string.
CreateCredentialExceptionalready exposes astable
type(verified againstandroidx.credentials:1.5.0).The case that surfaced this:
CreateCredentialNoCreateOptionException, whichCredential Manager throws when no provider will create a passkey — most commonly
Google Password Manager with no Google account signed in, or a device with no
provider installed. That's a reachable real-world state, and apps currently can't
detect it to offer a password fallback; they only get
"No create options available.".Change
CreateCredentialNoCreateOptionException→"NoCreateOption", matching theexisting naming style (
NoCredentials,UserCancelled,NotSupported).elsebranches withe.type(stable identifier) instead ofe.errorMessage(display text).NoCreateOptionError+ thehandleNativeErrorcase, so the code survives theJS layer rather than being swallowed by
default→NativeError.Notes
This follows the same shape as previously accepted mappings (#97
CredentialAlreadyExists,#86 iOS 1001 →
UserCancelled). Native-only + a JS switch case; no API breakage — theelsebranch previously returned an unspecified string, so nothing could have dependedon its value.
Verified on an Android emulator (API 36,
google_apis_playstore): without a Googleaccount the create call now rejects with
NoCreateOption; after signing in, passkeycreation completes normally.
🤖 Generated with Claude Code