
You implemented Firebase Phone Authentication, tested it once in the emulator, and shipped it. Now your users are hitting a wall: Firebase keeps saying the OTP is wrong even when they copy the code from the SMS perfectly. The frustration is real, and the cause is rarely a user typo.
This guide is for Android, iOS, and web developers who need to diagnose why Firebase rejects a one-time passcode. You’ll learn the exact API error codes that indicate deeper configuration problems, why auto-read features fetch stale codes, and a step-by-step fix path. By the end, you’ll have a checklist to eliminate 90% of OTP mismatch complaints before they reach your support inbox.
Use this when you see auth/invalid-verification-code in logs or when users report wrong code errors. Do not use this guide for issues with SMS delivery delays (codes arriving after expiry) or for re CAPTCHA flow failures that have different root causes.
Quick Answer: Why Firebase Keeps Saying Wrong OTP
- The submitted code doesn’t match the verificationId in the current session, not necessarily a user typo.
- The 60-second default TTL expires before submission, returning a mismatch instead of an expiry error.
- Auto-read parsing bugs (regex, leading zeros, stale SMS) submit the wrong digits.
- Resending a code invalidates the previous verificationId users entering the old code get a mismatch.
- A missing or stale verificationId (after Activity recreation) causes auth/missing-verification-id, which looks like a wrong code to users.
Why Firebase Keeps Saying Wrong OTP: The Real Reason It’s Not a Typo
Here’s the thing most developers miss: when Firebase says the OTP is wrong, it’s usually not because the user typed it incorrectly. The real culprit is often a mismatch between the verification ID stored in your app’s memory and the code being submitted.
Firebase links each OTP to a specific verification Id. If your app overwrites or clears that ID before the code is entered, Firebase rejects the code as invalid even when the code itself is perfectly correct. That’s the dirty little secret of Firebase’s error messaging: it’s vague by design, and wrong code can mean a half-dozen different things.
Let’s break down the usual suspects:
- Session state loss: The verification Id is held in memory, not persisted. If the Activity is recreated or the app is background, the ID is lost, and the submitted code references a dead session.
- Multi-instance conflict: If two Phone Auth Provider.verify Phone Number calls fire simultaneously, only the last verification Id is valid. The earlier code will always return invalid-verification-code.
- User error vs. system error: A wrong OTP alert can mask an expired token. Firebase’s default time-to-live is 60 seconds; a user who waits too long gets a mismatch, not an expiry message.
- Format stripping: If your code strips the leading zero or adds a whitespace, the token mismatch triggers a false negative.
The core issue is that Firebase’s error messaging is generic. It says wrong code for what are actually four distinct failures: expired token, stale ID, malformed input, or an actual typo. Your debugging job is to distinguish between them.
Firebase OTP Mismatch Error: What the API Is Actually Telling You
The Firebase OTP mismatch error is a server-side rejection, not a client-side validation failure. When you call sign In With Credential, Firebase compares the hash of the submitted code against the hash of the code sent to the device. A mismatch error means the code you submitted does not match the one-time token issued to that specific verification Id in that specific session.
Here’s what’s happening under the hood:
- Hash comparison: Firebase stores a salted hash of the OTP, not the raw code. This is why you cannot retrieve the correct code from the token; you must capture the SMS text.
- verification Id is the key: The ID points to the user’s phone number and the generated code. Incorrect code + correct ID = mismatch; correct code + incorrect ID = mismatch, too.
- Timeout is baked in: Firebase invalidates the code after the TTL expires. If the user submits after the window, the API returns a mismatch, not an expiration notice.
- Multi-factor interplay: If you have multiple Firebase projects (dev and prod) with the same SHA-1 fingerprint, the backend may route the SMS to the wrong project, causing a permanent mismatch.
Understanding this architecture changes how you debug. You stop asking why is the code wrong? and start asking which verification Id is my app submitting, and is it the one tied to this code?
The 6-Minute Clock Problem: Why Your Code Expires Before You Enter It
Here’s a misconception that bites developers hard: many assume Firebase OTPs last long enough for slow users, but the default time-to-live is 60 seconds, not 6 minutes. If a user takes longer than that, the server invalidates the code, and the client receives a generic wrong OTP message.
This is the most common cause of the wrong OTP after a complaint. Here’s the typical scenario: users type the first code after the window passes, then request a resend, and enter the old code. Mismatch. Every time.
- Default TTL: Firebase’s SMS code expires after 60 seconds. You can set force Resending Token to manage resends, but you cannot extend the TTL.
- User experience gap: On average, it takes users 25+ seconds to switch from the SMS app back to your app. If they pause to read the text or get distracted, they lose the race.
- The resend paradox: Requesting a new code does not invalidate the first one immediately. However, the first code’s TTL is still running. Entering the old code after a resend will cause a mismatch.
- Fix: Persist the timestamp: Store the verification Id and a timestamp in your app’s View Model so you can show a Code Expired, Resend state instead of a generic wrong code error.
The solution is not to ask users to type faster. It’s to make your UI aware of the clock. If the user’s submission arrives after the 60-second window, show Code expired. Resend now. instead of Incorrect code.
Firebase Wrong OTP API Response: Decoding auth/invalid-verification-code
The most common wrong OTP API response is auth/invalid-verification-code. This error means Firebase received a code that doesn’t match the one issued for the given verification Id. It is not a network error; it is a definitive token mismatch. If you see this error in your logs, the issue is almost always in the code submission flow, not in the SMS delivery.
Let’s get specific about what this error does and doesn’t tell you:
- Distinct from auth/invalid-phone-number: This error confirms the phone number was accepted; the problem is isolated to the code itself.
- Check the credential object: Ensure you are passing Phone Auth Provider credential(verification Id, code) with the correct ID. A stale ID in a singleton is a frequent bug.
- Log the full response: The Firebase Auth API returns a detailed message alongside the error code. Capture error. message to see if it specifies invalid verification code or expired.
- Retry logic is essential: You should not let the user retry the same code. The correct UX is to force a resend, and use force Resending Token to ensure a fresh token.
Refer to the Firebase Auth Error Codes Reference for the full taxonomy. When you see this error, your first move should be to log the verification Id and the code separately. Nine times out of ten, one of them is not what you expect.
Firebase Wrong OTP API Error Code: auth/missing-verification-id vs. Code Mismatch.
The error auth/missing-verification-id is distinct from a code mismatch. It means Firebase never received a verification Id to associate with the code. This error occurs when your app sends the credential without the ID a classic mistake after an Activity gets killed in the background. The code itself might be correct, but without a valid ID, Firebase cannot look up the token and returns a missing error.
Here’s when it shows up and how to handle it:
- When it appears: This error surfaces when the user backgrounds the app after requesting the code and returns after the OS has to recover the Activity’s memory.
- The fix: Save the verification Id to a Saved State Handle or persistent storage (like DataStore). Do not rely on a static variable.
- Compare error codes: missing-verification-id means the request is unroutable; invalid-verification-code means the code was wrong with a valid ID.
- Logging strategy: Always log both the error code and the verification Id nonce to correlate errors. Never log the raw phone number.
The distinction matters for your user messaging. If the ID is missing, telling the user to check the code is wrong they need to restart the verification process entirely.
The Resend Trap: Why Requesting a Second Code Breaks the First One
When a user taps Resend Code, Firebase issues a new OTP and a new verification Id. The old verification Id becomes invalid for code submission, but the old code is still technically valid until it expires. If your app updates the verification Id but the user enters the code from the first SMS, the API returns a mismatch error.
This is the Firebase wrong otp after resend scenario, and it’s almost 100% a client-side state handling issue. Here’s what’s happening:
- Server behavior: Firebase allows multiple codes to be issued, but it accepts only the most recent verification Id for sign-in.
- UI clarity: Your app should visually deprecate the first SMS. Change the button text to New Code Sent and clear the input field.
- The force Resending Token requirement: If you resend without this token, Firebase may block the request or return an error like quota Exceeded, which confuses the user into thinking the OTP is wrong.
- Timer reset: Reset your countdown timer to 60 seconds on every resend. A user hitting the submit button on a stale UI is a recipe for mismatches.
The fix is straightforward: when the user requests a resend, clear the input field and change the helper text to Use the code from the latest message. Never keep the old code visible next to a new verification Id.
Firebase Auto Read OTP Wrong: Why SMS Retrieval Fetches the Last Code
If Firebase auto-read returns the wrong code, the issue is often that your app reads the SMS inbox for the latest message instead of parsing the specific sender’s message. Carrier SMS aggregation can delay messages, and if a user receives two messages, your app may parse the first (older) code while the user submits the second. The result is a Firebase auto read otp wrong error that is entirely a data-sourcing issue.
Let’s unpack the scenarios:
- SMS Retriever API only reads its own messages: Google’s SMS Retriever does not read the whole inbox. If you’ve implemented a custom receiver, you might be hijacking messages you shouldn’t.
- Hash collision: The SMS Retriever requires an 11-character hash in the SMS body. If the hash is wrong, you won’t auto-read at all but if the hash is from an old build, you might read a previous message.
- Multi-sender conflict: If the user has WhatsApp or Telegram verification running in parallel, your app might pick the wrong code from the notification shade.
- Best practice: Bind the auto-read to the verification Id generation timestamp. Only accept a code parsed within 60 seconds of the SMS receipt time.
The SMS Retriever API is designed only to receive SMS that contain your app’s hash. Still, if your hash is outdated (because you didn’t re-register the SHA-1 after a keystore change), it can pick up messages from a previous build.
Firebase SMS Auto Read Incorrect Code: The Broadcast Receiver Formatting Bug
A common bug in Firebase SMS auto-read is the regex pattern used to extract the code. Firebase sends codes in a standardized format, but your Broadcast Receiver might trim digits, split the string incorrectly, or grab a non-numeric character. When the submitted code has a mismatched length (e.g., 5 digits instead of 6), Firebase returns a mismatch or an invalid-code error.
Here’s what to watch for:
- Message format: Firebase SMS codes appear like [#] Your code is 123456 with a hash signature. If you parse the hash before the code, your auto-fill logic grabs the signature instead.
- Regex pitfalls: Use a pattern that matches exactly 6 digits, not any digits or all digits after the last colon. Test with leading zeros many parsers strip them.
- Simulator vs. real device: Android emulators often deliver SMS with different formatting than real carriers. Always test on physical hardware and at least one US carrier and one EU carrier.
- Manual fallback is mandatory: Never rely solely on auto-read. Always offer a manual input field so the user can type the code if parsing fails.
Refer to the Android SMS Retriever API Guide for the exact message format. The most common regex mistake is using \d{4,6} instead of \d{6} ; this grabs the hash digits first.
Firebase OTP Autofill Wrong Verification: Android’s SMS Retriever vs. App Check
The Android SMS Retriever API can return a wrong code if your app has a SHA-1 fingerprint mismatch between the debug and release builds. Firebase uses the SHA-1 to validate the SMS sender. If the hash in the SMS body doesn’t match your app’s registered fingerprint, the auto-read fails or reads a stale hash from a previous build. The result is a verification mismatch that is impossible to fix client-side.
This is one of those issues that makes you want to throw your laptop across the room, because it works perfectly in development and breaks exactly when you go live. Key points:
- SHA-1 fingerprint check: Register both debug and release keystore fingerprints in the Firebase console. A missing fingerprint is a top cause of autofill wrong verification.
- App Check conflict: If App Check is enabled and the token is stale, OTP verification can fail with a permission-denied error that appears like a code mismatch. See the Firebase App Check documentation for token refresh best practices.
- Proguard/R8 obfuscation: Obfuscation can break the reflection-based SMS Retriever callback. Add proper keep rules for the auth library.
- Test the manual path: If auto-read fails but manual entry works, the problem is in the SMS parsing layer, not the OTP server logic.
The debug/release SHA-1 mismatch is the sneakiest issue here because it works in development and breaks in production. Always verify both fingerprints in the Firebase console before release.
Firebase Wrong OTP from Auto Retrieval: Test the Manual Entry Path First
When auto-retrieval delivers the wrong code, the fastest diagnostic is to hide auto-fill and prompt the user to enter the code manually. If the manual entry succeeds with the same code, your parsing pipeline is broken. If the manual entry also fails, the problem is upstream: either the code expired, or the verification Id is stale. This one test halves your debugging space.
Here’s your diagnostic workflow:
- Debugging workflow: Log the exact code parsed by your auto-read logic and compare it to the code in the SMS content manually.
- The off-by-one issue: Sometimes the SMS contains a code with a trailing period or space. Your parser might include that character, creating a 7-character string that fails validation.
- Carrier SMS delay: SMS latency can be high on certain global carriers (e.g., India, Brazil). The code may be delivered after the TTL expires, causing a mismatch.
- User education: Tell the user to check for a second message from your app’s sender if the first one times out. This reduces wrong OTP complaints significantly.
The manual-entry test is non-negotiable. It isolates the problem to either your parsing logic or your session management. Write a unit test for your regex with a code that starts with zero (e.g., 048201) to catch the most common parsing failure.
How to Fix Firebase OTP Not Matching Entered Code
To fix a mismatch, systematically test three variables: verification Id persistence, code parsing, and the timestamp. Step one: ensure the verification Id is saved in a lifecycle-aware container (ViewModel or persisted storage). Step two: log the raw code after parsing to confirm it’s exactly 6 digits. Step three: verify the user submits within 60 seconds. The fix is almost always one of these three.
Walk through this checklist in order:
- Step 1 Persistence: Store verification Id in Saved State Handle. Never in a companion object or static field. This fixes 80% of wrong OTP issues where the user switches apps.
- Step 2 Parsing: Write a unit test for your regex. Test with a leading-zero code (e.g., 048201), which is the most common cause of parse failures.
- Step 3 Timing: Add a visible countdown timer in the UI. When the timer hits zero, turn off the submit button and prompt for a resend.
- Step 4 Resend token: Always call resend Code with force Resending Token. Without it, the SDK may silently fail and return the old token, causing a false mismatch.
- Step 5 Cleanup: Clear the SMS input field on any error so the user cannot submit stale data.
Consult the official Firebase Phone Auth documentation for the complete force Resending Token flow. After Step 5, your Definition of Done is: the user can resend, wait, and verify within 60 seconds without a mismatch.
Stuck on a carrier that delays SMS and makes your OTP expire? Use a disposable number to test your flow without burning your real SIM. Get a number instantly at PVAPins pay per activation, no subscription.
Firebase Verification API Wrong Code Handling: Best Practices for Your Backend
If you are using Firebase’s REST API for verification, wrong code handling is about error mapping. The REST endpoint returns a structured error object with a code field. You should map auth/invalid-verification-code to a user-facing Incorrect code message, auth/expired-verification-code to Code expired, resend, and auth/invalid-verification-id to Session lost, restart. Do not catch all errors with a single generic message.
Here’s how to handle it properly:
- Server-side validation: If you handle OTP via a Cloud Function, always validate the ID token returned from sign In With Credential before issuing your own session cookie.
- Rate limiting: Firebase has aggressive quota limits for SMS sends. A quota Exceeded error can appear as a wrong OTP in the client if you don’t map the error code server-side.
- Error code taxonomy: Create a client-side mapping table for all Firebase Auth error codes. This prevents UX confusion like showing wrong code when the actual issue is too many requests.
- Logging (GDPR-safe): Do not log the full phone number. Hash the last 4 digits. Log the error code and the timestamp to correlate failures.
The backend is where you prevent the wrong code message from being a lie. If the user is rate-limited, tell them. If the session expired, tell them. Only show Incorrect code when Firebase actually means it.
When the Number Is the Problem: Testing Without a Real SIM
Sometimes the wrong OTP error is not a code problem, it’s a carrier or number problem. Firebase’s SMS delivery depends on the number being valid and provisioned for SMS. If you are testing with a VoIP number or a recycled prepaid SIM, the SMS may be delivered late or blocked entirely, causing the code to expire. Using a fresh, SMS-capable number can eliminate these environmental failures.
This is where things get interesting, because it’s also where most devs waste hours. Consider:
- VoIP number issue: Google’s SMS Retriever API often fails with VoIP numbers because the carrier does not route the SMS correctly.
- Recycled numbers: A number previously registered for Firebase on another account may trigger a silent block that never delivers the SMS.
- Global carrier latency: In some regions (e.g., parts of Southeast Asia and Latin America), SMS delivery can take 30+ seconds, cutting your testing window in half.
- Use a disposable number: For automated testing, rent a temporary number to validate your SMS flow end-to-end without burning your personal SIM.
If your Firebase setup looks correct but codes still fail, the issue may be the incoming number itself. Test with a fresh virtual number from PVAPins to isolate the issue. You can get a temporary virtual phone number delivered instantly, view codes in a real-time SMS verification dashboard, or rent a number for longer testing windows (1, 3, 7, 30 days) to test repeat OTPs and resend flows. Compare our SMS pricing by country to fit your testing budget. Higher acceptance starts with a clean number.
PVAPins is not affiliated with any app or website. Please follow each app’s terms and local regulations.
Preventing Wrong OTP Errors in Production: A Checklist for Developers
Prevention beats debugging. Lock down your OTP flow with a hard checklist: persist the verification Id lifecycle-aware, use force Resending Token for all resends, add a 60-second in-app countdown, parse the SMS with a strict 6-digit regex, and map every Firebase error code to a specific user message. This combination eliminates roughly 90% of wrong OTP complaints before they reach support.
Here’s what a solid production setup looks like:
- QA testing matrix: Test on 3 phone types (Pixel, Samsung, and a low-end Chinese OEM), 2 networks (one US, one non-US), and both manual entry and auto-read paths.
- Analytics events: Fire an otp_submit_attempt, otp_auto_read_success, and otp_expired event to track failure rates post-launch.
- Alerting: Set an alert threshold. If the invalid-verification-code error rate spikes above 5% in a 24-hour window, investigate your SDK version or carrier config immediately.
- Fallback channel: If you need a longer verification window than 60 seconds, consider allowing users to request a voice call code as an alternative, which Firebase supports natively.
- Documentation link: Point your team to Firebase’s official Auth documentation for edge cases around Android 14’s new credential manager behavior. Align your implementation with NIST guidelines for OTP security (SP 800-63B) to ensure your fallback channels meet best practices.
Need a number that lasts beyond 60 seconds? Rent a temporary number for 1, 3, or 7 days to test repeat OTPs, resend flows, and multi-session logins without interruption. Set up your rental in minutes. For automated testing, use our developer API to request numbers and poll OTP status programmatically. Browse our developer resources for more integration patterns.
Key Takeaways
- Firebase’s wrong OTP error is a server-side hash mismatch, not a user typo the verification Id and the code must be a matched pair.
- The 60-second TTL is non-negotiable. Your UI must enforce a visible countdown to prevent stale submissions.
- Auto-read failures are usually parsing bugs (leading zeros, regex, stale SMS) or SHA-1 fingerprint mismatches between debug and release builds.
- Always test the manual entry path first. If manual works but auto-read fails, your parsing is broken, not Firebase.
- For production, map every error code to a specific user message. Never show Incorrect code for an expired or missing session.
- If the problem persists, the number itself may be the issue. Test with a fresh, SMS-capable virtual number to isolate carrier problems.
FAQ
Is using a temporary number for Firebase verification legal?
It depends on the app’s terms of service, not just local law. For testing your own app’s SMS flow, using a temporary number is standard practice. Never use a temp number to create fake accounts on services that prohibit it. PVAPins is not affiliated with any app or website. Please follow each app’s terms and local regulations.
How long does a Firebase OTP code last?
The default time-to-live is 60 seconds. After that, the code is invalid, and resubmitting it triggers a wrong OTP error. Your UI should enforce a visible countdown to avoid this.
What is the difference between a one-time number and a rental number for testing?
A one-time number is a single-use temporary number for one OTP. A rental number stays active for 1, 3, 7, or up to 30 days, which is essential for testing resend flows, repeat logins, or multi-step verification in an app. PVAPins lets you choose by cost per activation.
What should I NOT use a temporary phone number for?
Don’t use temporary numbers to bypass fraud detection, create multiple fake accounts for incentives, or violate any app’s terms. Use them for legitimate app development testing and privacy.
Does Firebase deliver the wrong code to my auto-read feature?
It can if your parser reads a stale SMS or if your SHA-1 fingerprint is outdated. Always log the parsed code to confirm the exact logic before blaming the server.
Can I extend Firebase’s OTP timeout window?
No, you cannot configure the 60-second timeout on Firebase’s side. The fix is to trigger an automatic resend when the timer expires, so the user never sits on a dead code.
Compliance Note: PVAPins is not affiliated with any app or website. Please follow each app’s terms and local regulations.
Also Helpful: The same privacy-friendly tricks work across platforms. See our guide on “Fetch Keeps Saying Wrong OTP” if you use multiple inboxes.