microg/GmsCore · error · RuntimeException
No recaptcha token available
Error message
No recaptcha token available
What it means
FirebaseAuthService requires a reCAPTCHA token before sending an SMS verification code (phone auth). It resolves the token from, in order: the client-supplied request.recaptchaToken, the ReCaptchaOverlayService, or the legacy ReCaptchaActivity. If none is available it throws RuntimeException("No recaptcha token available"), meaning phone verification cannot proceed because Google's backend requires proof the request comes from a verified app.
Source
Thrown at firebase-auth/core/src/main/kotlin/org/microg/gms/firebase/auth/FirebaseAuthService.kt:376
Log.w(TAG, "callback: onFailure", e)
callbacks.onFailure(Status(CommonStatusCodes.INTERNAL_ERROR, e.message))
}
}
}
override fun sendEmailVerificationCompat(token: String?, actionCodeSettings: ActionCodeSettings?, callbacks: IFirebaseAuthCallbacks) {
sendEmailVerification(SendEmailVerificationWithSettingsAidlRequest().apply { this.token = token; this.settings = actionCodeSettings }, callbacks)
}
override fun sendVerificationCode(request: SendVerificationCodeAidlRequest, callbacks: IFirebaseAuthCallbacks) {
lifecycleScope.launchWhenStarted {
try {
Log.d(TAG, "sendVerificationCode")
val reCaptchaToken = when {
request.request.recaptchaToken != null -> request.request.recaptchaToken
ReCaptchaOverlayService.isSupported(context) -> ReCaptchaOverlayService.awaitToken(context, apiKey, getAuthorizedDomain())
ReCaptchaActivity.isSupported(context) -> ReCaptchaActivity.awaitToken(context, apiKey, getAuthorizedDomain())
else -> throw RuntimeException("No recaptcha token available")
}
var sessionInfo: String? = null
var registered = true
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
var smsCode: String? = null
for (message in intent.getSmsMessages()) {
smsCode = Regex("\\b([0-9]{6})\\b").find(message.messageBody)?.groups?.get(1)?.value
?: continue
Log.d(TAG, "Received SMS verification code: $smsCode")
break
}
if (smsCode == null) return
registered = false
context.unregisterReceiver(this)
try {
callbacks.onVerificationCompletedResponse(PhoneAuthCredential().apply {
this.phoneNumber = request.request.phoneNumberView on GitHub (pinned to 157c9d86ac)
Solutions
- Supply a valid recaptchaToken in the verification request obtained from the reCAPTCHA/Play Integrity verification flow for your app
- Call sendVerificationCode from a foreground Activity context so ReCaptchaActivity/overlay can present the challenge
- Verify microG is up to date and that ReCaptchaOverlayService/ReCaptchaActivity.isSupported(context) is true on the device
- Ensure the app's package name and signature are registered with the Firebase project so the authorized-domain check passes and token retrieval works
Example fix
// before: requesting code with no token, from background val resp = auth.sendVerificationCodeCompat(request) // after: fetch a token first and attach it val token = ReCaptchaOverlayService.awaitToken(context, apiKey, authorizedDomain) request.request.recaptchaToken = token val resp = auth.sendVerificationCodeCompat(request)
Defensive patterns
Strategy: fallback
Validate before calling
fun canSendVerificationCode(context: Context): Boolean = ReCaptchaOverlayService.isSupported(context) || ReCaptchaActivity.isSupported(context)
Try / catch
try {
auth.sendVerificationCodeCompat(request)
} catch (e: RuntimeException) {
if (e.message == "No recaptcha token available") {
// obtain a token via ReCaptchaOverlayService/ReCaptchaActivity, attach it, retry once
} else throw e
} Prevention
- Always call phone-auth verification from a foreground Activity so an interactive reCAPTCHA challenge can display
- Pre-fetch and attach a recaptchaToken when running from background components
- Keep microG and the client SDK updated; check isSupported() before initiating phone verification
- Register the app's package name and signature with the Firebase project so token flows succeed
When it happens
Trigger: Calling sendVerificationCode (via sendVerificationCodeCompat) when: the request carries no recaptchaToken, the device/app cannot display the ReCaptcha overlay (unsupported context or missing overlay support), and ReCaptchaActivity-based flow is also unsupported (no suitable Activity to launch, e.g. caller lacks activity context or anti-abuse flow disabled).
Common situations: A client app calling the microG phone-auth endpoint without obtaining a reCAPTCHA token first; running on a device/ROM where the overlay service can't be bound; background caller (Service/WorkManager) with no foreground Activity, so the interactive reCAPTCHA challenge can't be shown; microG version where both reCAPTCHA paths report isSupported=false.
Related errors
- deleteAll was set to true but keys were also provided
- Element in keys cannot be null or empty
- deleteAll=true but keys are provided
- retrieveAll was set to true but other constraint(s) was also
- Element in keys cannot be null or empty
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/d2568c6899845cef.
Report an issue: GitHub.