Skip to main content
deep-linking

Android App Links autoVerify Failed? 12 Causes and Fixes

autoVerify failed and links open the browser or a chooser? Check assetlinks.json with curl, then pm get-app-links on the device. 12 causes, each with a fix.

WarpLink Team16 min read

TL;DR: Android App Links autoVerify fails for 12 reasons, and the top production cause is an assetlinks.json that lists the upload key instead of the Play app signing key. Confirm the file with curl -sI https://yourdomain.com/.well-known/assetlinks.json (a direct 200, no redirect). Then run adb shell pm get-app-links com.example.myapp and expect verified next to each host.

No terminal handy? Paste your domain into the free assetlinks.json validator.

The 12 reasons fall into four layers: server (1 to 3), SHA-256 fingerprints (4 to 6), package and manifest (7 to 11), and device state (12).

Find the Failing Layer First

App Link verification has four layers: the server, the file contents, the manifest, and the device. Run the checks in this table from top to bottom. The first row whose result does not match is where to start.

SymptomCheckExpected resultReasons
Verification never completes, or every host failscurl -sI https://yourdomain.com/.well-known/assetlinks.json200, content-type: application/json, no Location header1 to 3
Works in debug, fails from PlayPlay Console, App integrity, Play app signingThe file lists the app signing key SHA-256, in uppercase4 to 6
One flavor failsadb shell pm list packages | grep yourappThe installed ID equals package_name7
A chooser dialog appearsOpen AndroidManifest.xmlandroid:autoVerify="true" on an https filter with the exact host8 to 11
The file and manifest look rightadb shell pm get-app-links com.example.myappverified next to each host12

Each reason follows one pattern: the symptom, the check, and the fix. App Links fail quietly. There is no crash and no error toast. The link opens a browser or an "Open with" chooser, and you are left guessing. A developer writing on Medium in late 2025 captured it: "Okay, here's where I wasted like 2 days of my life... the annoying SHA-256 certificate issue that had me pulling my hair out for days." For the iOS equivalent, see the Universal Links Open Safari? Fix Your apple-app-site-association File and Universal Links Not Working? 15 Causes and the Fix for Each.

1. A Redirect Sits in Front of the File

Symptom: Verification fails for every host, and the file looks fine in a browser.

Check:

Look for any 301 or 302. Android's troubleshooting guide says the system will not verify any App Links for your app if a redirect exists such as http://example.com to https://example.com, or example.com to www.example.com.

Fix: Remove the redirect so the file resolves with a direct 200 on the exact host in your manifest. This is the most common server-side cause.

2. The File Is Not Served as Valid JSON at the Right Path

Symptom: The URL answers 200 and the device still records a failure.

Check: The file must live at exactly https://yourdomain.com/.well-known/assetlinks.json. Unlike the iOS file, it has a .json extension. Confirm the content type and the body:

Android's docs say the file is served as application/json, so do not serve text/plain or text/html. If jq errors, the file is not valid JSON: a trailing comma, a stray comment, or a byte-order mark breaks parsing. The format is a JSON array of statement objects:

Fix: Move the file to /.well-known/, correct the content type, and repair the JSON. To check the same things without a terminal, paste your domain into our free assetlinks.json validator.

3. The Verifier Cannot Reach the File

Symptom: The file works from your laptop and not for the verifier.

Check: Look for four blockers. A login wall, basic auth, or a bot-protection challenge blocks the verifier, so the .well-known path has to be public. The HTTPS certificate must be valid and trusted: a self-signed or expired certificate fails, and there is no "proceed anyway." Android's troubleshooting guide also says example.com. (with a trailing period) must serve the same content as example.com. The device itself needs network access during verification.

Fix: Open the path to the public, renew or replace the certificate, and make the trailing-period host answer like the normal one.

4. The File Lists the Upload Key Instead of the Play App Signing Key

Symptom: App Links verify on a build you signed locally and fail on the build installed from Google Play.

Check: With Play App Signing, two keys exist. The upload key proves an upload is from you. Google's app signing key re-signs the app before distribution, and that is the certificate on the user's device. Android's docs say that the value from running keytool locally will usually not match the one on users' devices. Open Play Console, go to App integrity > Play app signing, and compare the App signing key certificate SHA-256 with your file.

Fix: Add the App signing key certificate SHA-256 to sha256_cert_fingerprints. Do not copy the Upload key certificate value. The same page shows a ready-made Digital Asset Links snippet.

5. A Signing Key You Actually Install Is Missing From the List

Symptom: Store builds verify and your internal APK or debug build does not, or the reverse.

Check: Read the SHA-256 of the build that fails.

Fix: The array is a list on purpose, and Android documents it as the way to support different versions of your app, such as debug and production builds. Add every certificate that signs a build you want verified:

Google's Statement List Generator outputs the exact JSON from a domain, package name, and SHA-256. Our assetlinks.json generator builds the same file.

6. The SHA-256 Has the Wrong Format

Symptom: The right key is in the file and verification still fails.

Check: Android's troubleshooting guide says the value must be uppercase, and lists a lowercase value as a common mistake, alongside signing with a debug certificate while only the release value is in the file. The format is colon-separated hex pairs, such as 14:6D:E9:.... A single wrong character fails verification with no useful error.

Fix: Copy the value from apksigner or Play Console rather than retyping it, keep it uppercase, and keep the colons.

7. The package_name Does Not Match the Installed applicationId

Symptom: One flavor or build type verifies and another does not.

Check: The package_name must exactly match the applicationId installed on the device, not the manifest package attribute if you remap it and not a flavor suffix you forgot.

If the device runs the pro flavor, the verifier looks for com.example.myapp.pro. Confirm the installed ID with adb shell pm list packages | grep example.

Fix: Add a statement object for each applicationId you ship. Add a second object rather than cramming two packages into one.

8. The Intent Filter Has No autoVerify

Symptom: The link works but shows a chooser dialog instead of opening the app directly, and pm get-app-links shows none after you waited and re-ran verification.

Check: Android's troubleshooting guide says each <intent-filter> must include android:autoVerify="true". Without it, Android never fetches your assetlinks.json. No autoVerify, no verification.

Fix:

9. The Filter Has the Wrong Shape

Symptom: autoVerify is set and the host never appears in the verification output.

Check: Verification only runs for a filter that uses the http or https data scheme (not a custom scheme) and includes the VIEW action plus the BROWSABLE and DEFAULT categories. If any is missing, the system does not treat the filter as an App Link.

Fix: Match the filter in reason 8 exactly, and keep the scheme as https.

Symptom: Links to yourdomain.com verify and links to go.yourdomain.com do not.

Check: android:host="yourdomain.com" does not cover www.yourdomain.com or links.yourdomain.com. The host in the filter, the host in your links, and the host serving assetlinks.json must be the same string. Android's docs say that if your app links support multiple host domains, you must publish assetlinks.json on each domain.

Fix: Declare every host you link to, and serve a correct file at each one's own /.well-known/assetlinks.json. A wildcard host like *.yourdomain.com needs a reachable file at each subdomain you actually use.

11. One Broken Host Fails the Rest

Symptom: Hosts you configured perfectly fail too.

Check: On Android 11 and lower, the app becomes the default handler only if the Digital Asset Links files match all the hosts in the manifest. One typo or one host without a file can fail all of them. Android's guide also says test-only non-verifiable links can fail verification for all App Links on Android 11 and lower. Android 12 and later query the file for each unique host name. Curl every host:

Fix: Fix or remove the broken host, and keep only hosts you can serve the file from. A failed host falls back to the chooser dialog on every version.

12. The Device Is Holding Stale or Unfinished State

Symptom: The server, file, and manifest all pass and the device still reports a failure.

Check: Ask the device what it recorded. Wait at least 20 seconds after an install, because verification is asynchronous.

Add --user cur to read the state for the current user. Read the state next to each domain:

StateMeaningNext step
verifiedThe domain passed and the app handles its linksDone
noneNothing recorded yet; verification may still be runningWait a few minutes, re-verify, check again; if it stays none, check autoVerify
1024 or higherA device-specific verifier code, not one causeConfirm network access, re-verify, check the file (reasons 1 to 3) and the SHA-256 (4 to 6)
legacy_failureThe legacy verifier rejected the domain for an unknown reasonReset and re-verify
approved / deniedForce-set through the shell, not earned by verificationFine for testing
migrated / restoredPreserved from a legacy result or a data restoreRe-verify to confirm
system_configuredApproved by the device configurationNot an error

Fix: On Android 12 and later, clear stale state and verify again (the reset command comes from Android's verification guide):

Android's documentation says to wait a few minutes for a manual verification. Check Settings > Apps > your app > Open by default > Add link too: a verified link shows as supported. On Android 15 and later, the system also re-verifies in the background, and a change to your file can take up to seven days to reach devices that do not re-verify manually. On Android 14 and lower, the system picks up a change only at install or update. The reliable reset is the three commands above, or an uninstall and reinstall.

To compare with what Google sees, query the Digital Asset Links API, the endpoint the verifier uses:

A healthy response has a statements array, and each entry carries target.androidApp.packageName and target.androidApp.certificate.sha256Fingerprint. An empty response sends you back to reasons 1 to 3. A SHA-256 that differs from your device's is reason 4 in black and white. On Android 17 and later, adb shell am start --debug-link -a android.intent.action.VIEW -d "https://yourdomain.com/product/123" shows which apps and intent filters match a URL.

The Short Version

Reasons 1 to 3 are about hosting a byte-perfect assetlinks.json. When you register an app in WarpLink, we generate the file from the package name and SHA-256 fingerprints you provide and serve it with Content-Type: application/json, no redirects, and no auth wall. Each app has its own link host, {handle}.aplnk.to, with its own assetlinks and AASA pair, because iOS and Android match a link host to one app. Verified custom domains get their own pair, and the files are regenerated when you update the app.

To check the result, open https://{host}/test on your app's host. It is a setup page served at the edge, so you can confirm the host is live before you run pm get-app-links. On your side, set the autoVerify filter with the exact host and register the Play App Signing SHA-256 from Play Console (reason 4). The SDK side is one call: pass the incoming intent URI to WarpLink.handleDeepLink(uri) from onCreate() and onNewIntent(), and it returns the destination, custom parameters, and attribution data on the main thread, for cold and warm start. The full setup is in the Android deep links docs, and the deep linking page shows what an app registration generates.

Frequently Asked Questions

Why do my Android App Links work in debug but not in production? Almost always the SHA-256 certificate fingerprint. Your debug build is signed with your debug or upload key, but Play App Signing re-signs the distributed app with Google's signing key, which has a different SHA-256. Your assetlinks.json lists the wrong one, so autoVerify passes locally and fails in the Play Store build. Copy the App signing key SHA-256 from Play Console under App integrity > Play app signing and add it to the file.

Where do I get the correct SHA-256 for assetlinks.json? For a Play-distributed app, copy it from Play Console: App integrity > Play app signing, under "App signing key certificate" (not "Upload key certificate"). For a locally signed release, read it from your release keystore with keytool -list -v -keystore release.jks -alias your-alias, or from a built APK with apksigner verify --print-certs app-release.apk. List every signing key you use in the sha256_cert_fingerprints array.

What does state 1024 or legacy_failure mean in pm get-app-links? 1024 (or higher) is a device-specific verifier code, and legacy_failure is a rejection with an unknown reason. Neither names one cause. Confirm network access, re-run adb shell pm verify-app-links --re-verify <package>, then check the file and any redirect (reasons 1 to 3) and the SHA-256 (reasons 4 to 6). Reset with adb shell pm set-app-links --package <pkg> 0 all, re-verify, and wait a few minutes before you read the state.

Why does autoVerify show a chooser dialog instead of opening my app? Either the intent filter is missing android:autoVerify="true" (so Android never verifies and defaults to the chooser), or verification ran and failed. Run adb shell pm get-app-links <package>: none means no result is recorded yet, so wait, re-run adb shell pm verify-app-links --re-verify <package>, and check again. 1024 or higher, or legacy_failure, has no single cause: confirm network access, then check the file and the SHA-256. Check the manifest and the JSON file as separate steps.

How do I force Android to re-verify App Links without reinstalling? Run adb shell pm verify-app-links --re-verify <package>, then check the result with adb shell pm get-app-links <package>. On Android 12 and later, reset stale state first with adb shell pm set-app-links --package <package> 0 all. Wait a few minutes before you read the result, and note that re-verification needs network access. Reinstalling still works as a fallback, since Android re-verifies at install time.

Does the SHA-256 in assetlinks.json need to be uppercase? Yes. Android's troubleshooting guide says the value should be uppercase, written as colon-separated hex pairs such as 14:6D:E9:.... A lowercase value is a common reason a correct-looking file still fails verification.

Sources

  • Android Developers, Verify Android App Links: the autoVerify filter, pm get-app-links, pm verify-app-links --re-verify, pm set-app-links --package <package> 0 all, the verification states, the 20 second and few-minute waits, the Android 11 and Android 12 host behavior, and the Android 15 re-verification delay.
  • Android Developers, Troubleshoot App Links: no redirects, uppercase values, the trailing-period host, the Play App Signing certificate, autoVerify on each filter, and am start --debug-link on Android 17 and later.
  • Android Developers, Declare website associations: file location, application/json, multiple certificates, multiple apps and the Play Console signing snippet.
  • Google, Digital Asset Links getting started and the statements.list reference: the statement format and the API that reason 12 queries.

Once your App Links verify and open the right screen, the next question is attribution: which link, campaign, or channel drove the open and the install, and how those opens show up in your analytics. That is where WarpLink picks up after the link resolves.

Check the file with the free assetlinks.json validator, then let WarpLink host and update this file so a key or package change is one edit.

Get your first deep link working today

Deep linking, install attribution, and real-time analytics in one SDK. Free for 10K clicks a month, no sales call.

WarpLink is link infrastructure that sends one link to the right place on iOS, Android, and the web, with install attribution and real-time analytics on every tap.

Stuck on setup? Email support@warplink.app and we will help you get one real link working.

WarpLink Team

Building affordable, reliable link infrastructure for mobile teams. Deep linking, install attribution, and real-time analytics in one SDK.