Short answer: iOS checks components rules in order and stops at the first match. If an exclude rule above your path matches first, or no rule covers the URL, or the case differs, that link opens Safari. Test the exact URL with sudo swcutil verify on a Mac.
What is happening
Path matching: the process in which iOS compares a tapped URL against the components rules in order and uses the first rule that matches, opening the app unless that rule has exclude: true.
Apple's components reference says: "The order that you use to specify the patterns in the array determines the order the system follows when looking for a match. The first match wins." So rule order matters as much as rule content.
- A URL must match every key a rule specifies. Apple's example
{"/":"abc","?":"def","#":"*"}matches/abc?defbut not/abcon its own. - Matching is case-sensitive by default (
caseSensitivedefaults totrue). percentEncodedalso defaults totrue, so keep that in mind for URLs with encoded characters.
Why does this happen?
Usually a broad rule sits above a narrow one, or a rule requires a query that real links do not carry. Mixed-case URLs from marketing tools are another common source.
- Order:
{ "/": "/*", "exclude": true }at the top blocks everything below it. - Too narrow:
/product/*does not match/products/1. - Query required: a rule with
"?": { "id": "?*" }fails for URLs withoutid. - Case:
/Promo/summerdoes not match/promo/*unless case sensitivity is off.
How to confirm it
- On a Mac, run
sudo swcutil verify -d example.com -j apple-app-site-association -u <failing URL>. It printsPattern "..." matched.orblocked match., so you can see whether a rule claims the URL. - On a device with Developer Mode on, open Settings > Developer > Universal Links > Diagnostics and enter the URL.
- Paste the link into Notes and long-press it. If the menu offers to open the app, the rule matches.
How to fix it
- Move every
excluderule above the broader rules it carves out. - Widen patterns that are too specific, using
*for any run of characters and?*for at least one character. - Remove query or fragment requirements that real links do not always include.
- For mixed-case URLs, add
"caseSensitive": falseto the rule, or set it indefaults. - Deploy and reinstall the app on the test device, then retest each URL.
{
"applinks": {
"defaults": { "caseSensitive": false },
"details": [
{
"appIDs": ["ABCDE12345.com.example.app"],
"components": [
{ "/": "/product/*/print", "exclude": true },
{ "/": "/product*/*" },
{ "/": "/promo/*" }
]
}
]
}
}
If only links typed into Safari fail, the file is fine; see typed links open Safari. List exclusions first when you write rules.