Skip to content
Dashboard

Testing & Troubleshooting

Deferred flow testing has platform constraints: full attribution path depends on store redirect chain.

  • Deferred matching is first-launch oriented.
  • Runtime callbacks do not re-trigger deferred matching logic.
  • Flutter bridge does not expose session reset API in 1.1.1.
  1. Uninstall the app from the device or simulator.
  2. Open a Detour link.
  3. Install and launch the app.
  4. Verify the initial intent and the resolved route in your UI logs.
  5. Relaunch the app and confirm the deferred behavior is not repeated.
Terminal window
adb shell am start -a android.intent.action.VIEW \
-d "https://<your-link-domain>/<link-token>" \
com.example.app
Terminal window
adb shell am start -a android.intent.action.VIEW \
-d "myapp://product/42" \
com.example.app
Terminal window
xcrun simctl openurl booted "myapp://product/42"
Terminal window
xcrun simctl openurl booted "https://<your-link-domain>/<link-token>"

Install referrer click_id is often unavailable in local/dev-store scenarios. In that case matching falls back to probabilistic flow. For local install referrer testing workarounds, see How to test the Play Store Install Referrer API.

If an installed app does not open Detour links, the Dashboard SHA-256 probably does not match the key that signed the build on your device:

How you install the appSHA-256 to useWhere to find it
Google Play, any trackPlay App Signing keyPlay Console → Protected with Play → Manage Play app signing → App signing key certificate
flutter run / flutter build apk --debugAGP default debug keystorekeytool -list -v -keystore ~/.android/debug.keystore -storepass android, or ./gradlew signingReport
Release build with your own keystoreYour release keystorekeytool -list -v -keystore <path-to-your.keystore>

The Flutter template signs release with the debug config until you add your own release keystore, so a fresh flutter build apk --release is still debug-signed.

To check any build directly: apksigner verify --print-certs build/app/outputs/flutter-apk/app-debug.apk. The complete procedure is described in Finding your Android SHA-256 fingerprint.

  • No match found (404)

    • Check timestamps. The click may be older than the match window (15 minutes).
    • Confirm the click was recorded in your Detour Dashboard.
    • On Android deterministic flow: confirm click_id is present in the install referrer.
  • 429 Too Many Requests

    • Detour limits deferred link matching per device and IP address, and per app. Wait between reinstall tests on one device. For tests on many devices at once, create a separate app for testing in the Dashboard, because each app has its own credentials and its own limit.
  • NOT_CONFIGURED platform error

    • resolveInitialLink() and processLink() raise it on both platforms. On Android, logEvent() and logRetention() raise it too.
    • Await DetourService.start(...) or DetourFlutterPlugin.configure(...) before you call these methods. If configure(...) failed, fix that error first.
  • INVALID_ARGS platform error

    • Android only. configure(...) raises it when apiKey or appID is empty, processLink(...) when url is empty, and logRetention(...) when eventName is empty. A value that contains only whitespace counts as empty.
    • Pass non-empty values.
  • NO_ACTIVITY platform error

    • On Android, configure(...) ran in a Flutter engine that has no attached activity, such as a separate engine started for background work.
    • Call DetourService.start(...) or DetourFlutterPlugin.configure(...) from your app’s UI code, not from a background handler.
  • NATIVE_ERROR platform error

    • Android only. resolveInitialLink() and processLink() raise it, and linkStream emits it as an error event, when the native SDK fails to process a link. DetourService.start() throws the same error and leaves isInitialLinkProcessed at false, so catch it if your startup flow waits for that flag.
    • A failed deferred match request on first launch raises it. When the server responded, the message starts with the HTTP status code: [401] for a wrong apiKey or appID, [402] when your organization is over its plan’s click limit, and [429] for too many match requests. Without a status code, the request did not complete.
  • iOS clipboard not read

    • Ensure shouldUseClipboard: true is set in DetourConfig.
    • Ensure the copy-link feature is enabled in the Detour Dashboard for your iOS app configuration.
    • The link must be copied to the clipboard before the app is opened, because the clipboard is only read during resolveInitialLink().
  • Deferred link not returned on subsequent test runs

    • Deferred matching is first-launch based. Reinstall the app for a clean re-test.
  • Android release build fails with Type com.swmansion.detour.BuildConfig is defined multiple times

    • Debug builds of the same project succeed.
    • detour_flutter_plugin 1.1.1 uses the Android namespace com.swmansion.detour, which the native Detour SDK also uses. The release build then contains two classes named com.swmansion.detour.BuildConfig.
    • No 1.1.x release fixes this. Upgrade to detour_flutter_plugin: ^1.2.1 and run flutter pub get.
  • Android:
    • adb logcat | grep -i detour
  • iOS simulator:
    • xcrun simctl spawn booted log stream --predicate 'subsystem == "com.swmansion.detour"'

For full runnable setup and commands, use Examples.