Documentation
When it does not work
Every failure state, what it means, and what to do about it. Including the Apple caching delay that makes a correct setup look broken for up to 24 hours.
Start here: Apple caches your association file for up to 24 hours
This is the commonest reason a correct setup appears broken, and if you read nothing else on this page, read this.
iOS does not fetch your association file from us. It fetches it from Apple’s CDN, which fetches it from us on its own schedule and then caches it — for up to 24 hours. So if you configure everything correctly right now and test in two minutes, iOS may still be holding the version from before you configured anything, which claimed nothing, and your link will open Safari.
Nothing is wrong. Nothing needs changing. There is a flag for this:
applinks:YOUR-KEY.links.quberoute.com?mode=developer?mode=developer tells iOS to fetch the file directly from us every time, bypassing Apple’s cache entirely. It works on a device with Developer Mode enabled (Settings → Privacy & Security → Developer Mode) and it makes the loop seconds instead of hours.
Remove it before you ship. With it in place, every launch of your released app fetches the file from us directly, which is slower for your users and pointless once the configuration has settled.
After removing it, expect up to 24 hours before Apple’s cache catches up. Plan the release accordingly, and do not interpret the gap as a fault.
The link opens Safari instead of the app
In the order these are actually the cause:
- Apple’s cache. See above. Add
?mode=developerand try again. - You typed the link into Safari’s address bar. iOS deliberately does not open apps for links typed into the address bar. Put the link in a note, a message or an email and tap it from there.
- Associated Domains is not on the App ID. Check your Apple Developer account, then regenerate the provisioning profile. Xcode with automatic signing usually handles this; when it does not, nothing else will work until it does.
- The host does not match. Live and test are different hosts —
YOUR-KEYandYOUR-KEY-test. A test link with only the live domain declared will not open the app. - You are inside an in-app browser. Instagram, Facebook, Gmail and others often keep the link inside their own browser rather than handing it to iOS. Nothing is misconfigured and there is no setting that changes it — it is the embedding app’s decision. Your web fallback is what the person sees.
- The app was installed from Xcode over a previous build. Delete the app from the device and install again; iOS caches the entitlement.
Before you work through that list, check our own file is right: the app settings page has a validator that fetches your association file, checks every one of Apple’s requirements against the real response, and can also ask Apple’s CDN what it is currently serving. If ours is correct and Apple’s is stale, that tells you it is the cache and not you.
The app opens, but onLink never fires
@capacitor/appis not installed. That plugin is how a launch URL reaches the SDK at all; without it, links open your app and nothing else happens. Runnpm install @capacitor/app && npx cap syncand rebuild. The SDK reports this throughonErroron the first launch, so pass one while you are integrating — see below.- You registered
onLinktoo late. The SDK holds a link that arrives before your handler exists and delivers it the moment you register — but if you register it after anawaiton something slow, your user has already seen the wrong screen. Register it immediately afterinit. - The alias does not exist in this environment. A test key resolving a live link gets
wrong_environment, with a message saying so. - Your handler threw. The SDK catches exceptions from your handler so your bug does not become our crash — but that means a broken router looks like nothing happening. Pass
onErrortoinitwhile you are developing.
const qr = await QubeRoute.init({
key: 'qr_test_YOUR_KEY',
onError: error => console.error('[QubeRoute]', error),
})What the server tells you, and what each answer means
| What comes back | What it means |
|---|---|
wrong_key_kind | You have shipped a secret key inside your app. Create a publishable one and revoke this one — if the build was released, anybody who downloaded it has it. |
unauthorised | The key is not one we recognise, or it has been revoked. Copy it again from the SDK setup page. |
wrong_environment | A test key was asked about a live link, or the reverse. Use the key that matches the environment you are testing. |
no_such_link | The alias does not exist in this app and environment. Usually a link created in the other environment. |
not_your_link | The address belongs to a different app. Check the link host in your Associated Domains entry. |
rate_limited | Too many requests from this network address. It is per address rather than per app, and it resets shortly. Common when reinstalling repeatedly while testing. |
temporarily_unavailable | Ours, not yours. Events are kept and retried; a deferred match is not retried, because an install is only ever matched once. |
A deferred install was not attributed
Often correct rather than broken. The match endpoint tells you which kind of “no” it was:
no_candidates— no click in the window that could be this device. Usually the person tapped on wifi and opened the app on cellular, which changes the network address.below_threshold— something was close, but not close enough to assert. We do not report guesses as installs.ambiguous— two or more different links fitted equally well, so we attributed none. Common on a shared network.disabled_by_app— probabilistic matching is switched off for this app, in its settings.
The expected rates are on the deferred matching page, including the case where the method does badly.
Events are not appearing
- Events are queued when the device is offline and sent with the next one. The queue holds a hundred; beyond that the oldest are dropped.
- An event with no name is dropped, and the response says how many were.
- A value needs a currency.
{ value: 4.99 }with nocurrencyrecords the event without the money. - Test and live are separate. An event from a test key never appears in a live report.
Still stuck? Write to [email protected] with your app key and roughly when you tested, and we will look at what our server actually saw.
Ask the documentation
It answers from these pages only, and links what it used. If the answer is not here it says so rather than guessing — then email [email protected].