Appy
← 返回博客
故障排查

Universal Links 与 App Links 错误码详解

SWCERR00101、SWCERR00301、legacy_failure、1026:每个 Universal Links 和 Android App Links 错误到底是什么意思,在哪里能看到,以及怎样修好才能让应用重新打开。也可以交给 Appy 的免费验证工具,几秒钟就帮你找出问题。

2026年10月9日•阅读约 9 分钟

先确认它真的坏了

很多“Universal Links 不生效”的反馈,其实是链接完全在按 Apple 的设计工作。Apple 的技术说明 TN3155 列出了应用本就不该被打开的几种情况:在 Safari 地址栏里输入或粘贴的 URL 属于直接导航,会留在浏览器里;指向当前页面同一域名的链接,也会留在浏览器里;第三方浏览器,包括其他应用内置的浏览器,会自行决定要不要把链接交给你的应用。

所以,动任何文件之前,先老老实实测一遍。把链接粘贴到 iPhone 的备忘录里,然后长按。如果配置正确,菜单里除了用浏览器打开,还会提供用你的应用打开的选项。用户在这里选了什么,就会成为该域名的默认行为,这也是昨天还正常的链接今天却打开 Safari 的又一个隐蔽原因。

如果备忘录里没有应用选项,就是关联出了问题,错误码会告诉你问题在哪。

捷径:Appy 免费验证工具

打开终端之前,先把你的域名粘贴到 Appy 的 Universal Links 验证工具里。它会分别从你自己的服务器和 Apple 的 CDN 抓取 apple-app-site-association 文件,让你一眼看出 Apple 手里的文件和你的是不是同一份。它还会通过 Google 的 Digital Asset Links API 查询 Android 从你的 assetlinks.json 里读到了什么。免费、无需注册,结果就一页,直接发给开发同事即可。

如果问题出在文件本身,Appy 的 AASA 与 assetlinks.json 生成器会根据你的 Team ID、bundle ID 和 SHA-256 指纹生成这两个文件。本文其余部分逐一讲解每个错误,验证工具一旦标出问题,你就清楚该修哪里。

问问 Apple 的 CDN 手里有什么

从 iOS 14 起,手机不再从你的服务器获取 apple-app-site-association 文件,而是从 Apple 的 CDN 获取,再由 CDN 去你那里抓取。所以第一个问题不是“我的文件对不对”,而是“Apple 手里的是什么”。

Apple CDN 为你的域名保存了什么

curl -sD - "https://app-site-association.cdn-apple.com/a/v1/links.example.com" -o /dev/null

出错的域名会这样响应

HTTP/1.1 404 Not Found
Apple-Failure-Reason: SWCERR00101 Bad HTTP Response: 404 Not Found
Cache-Control: max-age=3600,public

CDN 眼中的你的服务器

curl -v -A "AASA-Bot/1.0" https://links.example.com/.well-known/apple-app-site-association
我们在 2026 年 10 月查询 CDN 时,正常文件返回的是 max-age=21600(6 小时),失败结果返回的是 max-age=3600(1 小时)。你没有办法自己清除这份缓存。

SWCERR 错误码及修复方法

Apple 没有公布这些错误码的列表。下面是 Apple CDN 在 Apple-Failure-Reason 响应头里返回的消息,每一条都在 Apple Developer Forums 的讨论或我们自己对 CDN 的请求中得到过确认。

01

SWCERR00101 · Bad HTTP Response: 404 Not Found

CDN 请求你的文件,拿到的却不是 200。最常见的情况是文件放在根域名上,而 entitlement 里写的是子域名,或者反过来。applinks: 里的每个主机都需要在 https://that-host/.well-known/apple-app-site-association 放一份自己的文件。如果这里是 502,说明 Apple 来请求时你的源站宕机了。

02

SWCERR00201 · Insecure (non-https) redirects forbidden

文件的 URL 重定向到了一个 http:// 地址。请在每个域名上直接通过 HTTPS 提供该文件。Apple 文档要求完全不能重定向;在我们的测试中,CDN 会跟随 https 到 https 的重定向,但降级到 http 一定失败。

03

SWCERR00202 · Connections to private/reserved IP addresses are not allowed

主机名解析到了私有或保留地址,所以 Apple 不会去连接。只存在于 VPN 内部的 staging 域名经常遇到这种情况。这类域名请用开发者模式(下文会讲),生产环境则用公网主机。

04

SWCERR00301 · Timeout

Apple 的抓取程序等了半天,没收到任何响应头。常见原因是防火墙、地域屏蔽,以及会对陌生客户端发起验证的机器人防护。Apple 说这个文件必须能从任何 IP 访问,而且不公布自己的 IP 段,所以请对所有人放行这个路径。

05

SWCERR00302 · Network error (temporary)

临时故障,通常和 DNS 有关。如果你的 DNS 没问题,一般下一次抓取时就会消失;对失败结果来说,下一次抓取会在一小时内发生。

06

SWCERR00303 · TLS error

证书过期、签发给了别的主机、是自签名证书,或者握手失败。Apple 要求使用受公众信任、并且准确覆盖该主机名的证书。example.com 的证书并不覆盖 links.example.com,除非证书里明确写了它。

07

SWCERR00305 · Network error

CDN 连上了,但传输中断了:EOF、connection refused,或者服务器声称做了压缩却没有压缩时出现的 gzip: invalid header。请检查这个路径的 WAF 和压缩设置。

08

SWCERR00401 · Bad JSON content

CDN 拿到的不是 JSON,通常是 HTML 的人机验证页或登录页。“invalid character ‘<’”这条细节一看便知。论坛里一位 Apple 工程师给出的解决办法是:让服务器对任何 user agent(包括 AASA-Bot/*)都直接返回原始文件。

用 swcutil 检查路径

Apple 拿到文件之后,下一个问题是你的链接能否与它匹配。在 Mac 上,swcutil 可以拿本地文件副本对真实 URL 做测试,Apple 工程师推荐用这个方法,而不是开发者模式。

下载测试

sudo swcutil dl -d links.example.com

匹配测试

sudo swcutil verify -d links.example.com -j ./apple-app-site-association -u https://links.example.com/promo

匹配成功时的输出

{ s = applinks, a = ABCD123.com.example.app, d = links.example.com }:
Pattern "https://links.example.com/promo" matched.
“blocked match”表示该路径是被刻意排除的,或者没有被你的 components 覆盖。不要在同一个文件里混用当前的 appIDs + components 格式和旧的 appID + paths 格式。

手机自己怎么看

打开开发者模式后,在“设置 › 开发者 › Universal Links”里有一个 Diagnostics 页面:输入完整 URL,它会告诉你是否有已安装的应用认领了这个链接。想看完整情况,就抓一份 sysdiagnose,打开 swcutil_show.txt,搜索你的 app ID,看其中三行。

Site/Fmwk Approval 应该显示 approved。如果是 unspecified 或 denied,说明手机从没为这个应用和域名拿到过经批准的文件:检查 entitlement、能否公开访问以及 Team ID 前缀。User Approval 显示用户是否为这个域名选择了浏览器。Last Checked 和 Next Check 显示 Apple 上次抓取你文件的时间。

最后这一点解释了大多数“我已经修好了,可什么都没变”的情况。安装之后,手机大约每周才重新检查一次文件。想马上测试修复效果,就重装应用。对于 staging 环境,在 applinks 条目里加上 ?mode=developer:这样会绕过 CDN,但只对使用开发证书签名的构建生效,而且只在你已开启该选项的设备上生效。

值得记住的几个数字

我们测试中 Apple CDN 保留正常文件的时长
6 小时

我们测试中 Apple CDN 保留正常文件的时长

保留失败结果的时长
1 小时

保留失败结果的时长

iPhone 安装后重新检查的频率
约 1 周

iPhone 安装后重新检查的频率

Android 上检查验证结果前至少要等待的时间
20 秒

Android 上检查验证结果前至少要等待的时间

Android App Links:pm get-app-links 报告的状态

Android 中间没有 CDN。设备上的验证程序会自己去抓取 https://your-host/.well-known/assetlinks.json;从 Android 12 起,未通过验证的链接不再弹出选择框,而是直接在浏览器中打开。所以缺少证书指纹时,表现恰恰就是“链接能用,只是不在我的应用里打开”。

Android 12 还改变了多个主机的判定方式。现在每个主机单独验证;在 Android 11 及更低版本上,只要有一个主机验证失败,所有主机都会失败。另外在 Android 15 上,对 assetlinks.json 的修改最多可能需要七天才能到达所有设备。

在你的电脑上重新运行验证

重置、验证、读取

adb shell pm set-app-links --package com.example.app 0 all
adb shell pm verify-app-links --re-verify com.example.app
adb shell pm get-app-links com.example.app

典型输出

example.com: verified
sub.example.com: legacy_failure
example.org: 1026
全新安装后至少等 20 秒再读取结果,验证是在后台进行的。

每种状态的含义

01

verified

域名已通过验证。如果链接仍然打开浏览器,就去看 intent filter:android:autoVerify="true"、BROWSABLE 类别,以及 http 和 https 两种 scheme。

02

none

还没有任何记录。等几分钟,再运行一次 verify-app-links。

03

legacy_failure

旧版验证程序拒绝了这个域名,却没说原因。先从文件本身查起:HTTP 200、application/json、HTTPS、没有重定向。

04

1024 及以上(例如 1026)

特定验证程序的错误。Android 文档指向网络和托管:同样是 200、JSON、HTTPS、不重定向这几条规则。

05

approved / denied

由 shell 命令强制设定,而不是验证得出的。在相信任何结果之前,先用 set-app-links 重置。

06

migrated / restored / system_configured

从旧版验证迁移而来、随用户数据恢复,或由设备配置设定。这些不是错误,但也不能证明你的文件今天能正常工作。

在你电脑上正确、到了 Play 商店却出错的指纹

Android 上最常见的故障和托管毫无关系。启用 Play App Signing 后,Google 会用自己的应用签名密钥重新签署你的应用。你用 keytool 从上传密钥得到的 SHA-256,并不是用户手机上的那个,所以本地构建能通过,正式版构建却失败。

请改为从 Play Console › Release › Setup › App signing 复制指纹。sha256_cert_fingerprints 数组可以放多个值,所以把调试密钥也留在里面,用大写。还要记住:从 example.com 重定向到 www.example.com,或从 http 重定向到 https,都意味着 Android 不会验证你的任何链接。

看看 Google 从你的文件里读到了什么

Digital Asset Links API

curl "https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urls"
如果 statements 列表为空,说明 Google 没能读取文件:非 200 响应、重定向或不受信任的证书,最后都会落到这个结果。

修文件的同时,推广照常进行

关联文件坏了,不该让你损失安装量。在任何套餐下,Appy 链接都会把每部手机送到对应的应用商店,包括华为应用市场;在 Pro 套餐下,它还会先尝试打开你的应用,已经装了应用的人会直接进入应用。不需要 AASA 文件,不需要 SDK,也不用发新版本。等 Universal Links 恢复正常,继续用同一条 Appy 链接就行,已经印出去的码和发出去的帖子都不用改。

appy.to/yourapp

排查期间照常工作

  • iPhone你的应用(Pro)或 App Store
  • Android你的应用(Pro)或 Google Play
  • 华为华为应用市场
  • 电脑你的网站
商店路由在所有套餐中都可用,包括免费版。打开已安装的应用属于 Pro 功能,每月 $9.99 起。

延伸阅读

错误码常见问题

在哪里能看到 SWCERR 错误码?

请求 https://app-site-association.cdn-apple.com/a/v1/your-domain 时的 Apple-Failure-Reason 响应头里、Mac 上 swcutil dl 的输出里,以及设备上的 swcd 日志里。

怎样让 Apple 拿到我修好的 AASA 文件?

Apple 的 CDN 缓存无法手动清除。缓存过期后它会重新抓取,在我们的测试中,失败结果的缓存时间是一小时。之后在测试手机上重装应用,让它去拿新副本,而不是等每周一次的检查。

有没有能一次检查所有这些的工具?

有。Appy 的 Universal Links 验证工具免费,而且无需注册。它会检查你服务器上和 Apple CDN 上的 AASA 文件,并通过 Google 的 Digital Asset Links API 检查你的 assetlinks.json,然后告诉你该修什么。

apple-app-site-association 文件有大小限制吗?

Apple 在 2016 年的文档中写过 128 KB 的上限。现在的文档没再提,但让文件保持小巧,就不用操心这个问题。

为什么我在 Safari 里输入链接时,打开的是浏览器?

这是预期行为。按设计,手动输入的 URL 和同一域名内的链接都会留在浏览器里。请改从备忘录或信息里测试。

Android 上的 legacy_failure 是什么意思?

旧版验证程序拒绝了这个域名,而 Android 不告诉你原因。检查 assetlinks.json 是否通过 HTTPS 以 application/json 返回 200 且没有重定向,并确认里面列出了 Play App Signing 的指纹。

能不能绕开这一切?

部分可以。在 Pro 套餐下,Appy 链接会先尝试你应用的 URL scheme,失败后再转到正确的应用商店,所以不需要在你自己的域名上放 AASA 文件也能工作。真正的 Universal Links 仍然需要上面的配置。

继续探索

故障排查
2026年8月14日
10 分钟阅读

Android App Links 验证失败:用 adb 五分钟定位问题

从 Android 12 起,域名验证未通过的 App Link 会在浏览器而非你的应用中打开——静默发生,而且并非每台设备都一样。这份 adb 排查清单能快速找到原因。

android app links
assetlinks.json
app links verification
adb
阅读文章
故障排查
2026年3月7日
11 分钟阅读

通用链接打开 Safari?修复 AASA、App Links、重定向与响应头

可执行排障流程,帮助你修复打开浏览器而非 App 的通用链接问题。

universal links
app links
aasa
assetlinks
阅读文章
指南
2026年10月9日
10 分钟阅读

应用内浏览器如何处理深度链接:Instagram、TikTok、Facebook、Gmail、Telegram 等

同一条链接,在 Safari 里能打开应用,到了 Instagram 里就失灵。本文梳理每个应用用的是哪种浏览器、Apple、Google 和 Chrome 的规则,以及你能做些什么。

in-app browser
universal links
app links
instagram
阅读文章

想看更多内容?浏览 博客全部主题.

别再让坏链接吃掉你的点击

用免费验证工具找出出错的文件,同时用 Appy 链接让每场推广照常运转:任何套餐都能送到正确的应用商店,Pro 套餐直接打开你的应用。