Коды ошибок Universal Links и App Links: что они значат
SWCERR00101, SWCERR00301, legacy_failure, 1026: что на самом деле означает каждая ошибка Universal Links и Android App Links, где её увидеть и что исправить, чтобы приложение снова открывалось. Или доверьте поиск бесплатному валидатору Appy: он найдёт проблему за секунды.
Сначала убедитесь, что всё действительно сломано
Многие жалобы «Universal Links не работают» на деле описывают ссылки, которые ведут себя ровно так, как задумала Apple. В техническом документе TN3155 Apple перечисляет случаи, когда приложение и не должно открываться: URL, набранный или вставленный в адресную строку Safari, — это прямая навигация, и браузер оставляет его себе. Ссылка на тот же домен, что и текущая страница, тоже остаётся в браузере. А сторонние браузеры, включая встроенные в другие приложения, сами решают, передавать ли ссылку вашему приложению.
Поэтому сначала проверьте честно и только потом трогайте файлы. Вставьте ссылку в Заметки на iPhone и долго нажмите на неё. Если всё настроено правильно, меню предложит открыть её не только в браузере, но и в вашем приложении. Что пользователь выберет в этом меню, станет поведением по умолчанию для домена — ещё одна незаметная причина, по которой ссылка, работавшая вчера, сегодня открывает Safari.
Если Заметки не предлагают приложение, проблема в связке с доменом, и код ошибки подскажет, в чём именно.
Короткий путь: бесплатный валидатор Appy
Прежде чем открывать терминал, вставьте свой домен в валидатор Universal Links от Appy. Он загружает файл apple-app-site-association отдельно с вашего сервера и из CDN Apple, так что вы сразу видите, тот ли файл у Apple, что и у вас. Заодно он спрашивает у Digital Asset Links API от Google, что Android читает из вашего assetlinks.json. Бесплатно, без регистрации, а результат умещается на одной странице, которую можно сразу переслать разработчикам.
Если проблема в самих файлах, генератор AASA и assetlinks.json от Appy соберёт оба по вашему Team ID, bundle ID и отпечатку SHA-256. Дальше в руководстве разобрана каждая ошибка, так что, когда валидатор её покажет, вы будете точно знать, что исправлять.
Спросите у CDN Apple, что у него есть
Начиная с iOS 14 телефоны никогда не скачивают файл apple-app-site-association с вашего сервера. Они получают его из CDN Apple, а CDN забирает его у вас. Поэтому первый вопрос не «правильный ли у меня файл?», а «что есть у Apple?».
Что CDN Apple хранит для вашего домена
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Коды SWCERR и как их исправить
Apple не публикует список этих кодов. Ниже — сообщения, которые CDN Apple возвращает в заголовке Apple-Failure-Reason; каждое подтверждено в обсуждениях на Apple Developer Forums или нашими собственными запросами к CDN.
SWCERR00101 · Bad HTTP Response: 404 Not Found
CDN запросил ваш файл и получил что-то кроме 200. Чаще всего файл лежит на корневом домене, а в entitlement указан поддомен, или наоборот. Каждому хосту в applinks: нужен свой файл по адресу https://that-host/.well-known/apple-app-site-association. Ответ 502 здесь значит, что ваш исходный сервер лежал, когда Apple к нему обратилась.
SWCERR00201 · Insecure (non-https) redirects forbidden
URL файла перенаправляет на адрес http://. Отдавайте файл напрямую по HTTPS на каждом домене. В документации Apple сказано, что редиректов не должно быть вообще; в наших тестах CDN прошёл по редиректу с https на https, но переход на http всегда заканчивается ошибкой.
SWCERR00202 · Connections to private/reserved IP addresses are not allowed
Имя хоста указывает на частный или зарезервированный IP-адрес, поэтому Apple не подключается. Типичная история для staging-доменов, которые существуют только внутри VPN. Для них используйте режим разработчика (о нём ниже), а для продакшена — публичный хост.
SWCERR00301 · Timeout
Загрузчик Apple ждал и так и не получил заголовков. Обычно виноваты файрволы, геоблокировка и защита от ботов, которая устраивает проверку незнакомым клиентам. Apple требует, чтобы файл был доступен с любого IP, и не публикует свои диапазоны адресов, так что откройте этот путь для всех.
SWCERR00302 · Network error (temporary)
Временный сбой, часто из-за DNS. Если с DNS всё в порядке, ошибка обычно уходит при следующей загрузке, а после сбоя она происходит в течение часа.
SWCERR00303 · TLS error
Сертификат просрочен, выпущен для другого хоста, самоподписан или TLS-рукопожатие не удалось. Apple нужен публично доверенный сертификат, который покрывает именно это имя хоста. Сертификат для example.com не покрывает links.example.com, если это в нём явно не указано.
SWCERR00305 · Network error
CDN подключился, но передача оборвалась: EOF, connection refused или gzip: invalid header, когда сервер заявляет сжатие, которого на самом деле нет. Проверьте настройки WAF и сжатия для этого пути.
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.Что думает сам телефон
Если включён режим разработчика, в разделе Настройки › Для разработчиков › Universal Links есть экран Diagnostics: введите полный URL, и он покажет, заявляет ли на него права какое-нибудь установленное приложение. Чтобы увидеть всю картину, снимите sysdiagnose и откройте swcutil_show.txt. Найдите ID своего приложения и прочитайте три строки.
В Site/Fmwk Approval должно стоять approved. Unspecified или denied значит, что телефон так и не получил одобренный файл для этого приложения и домена: проверьте entitlement, публичный доступ и префикс Team ID. User Approval показывает, выбрал ли человек браузер для этого домена. Last Checked и Next Check показывают, когда Apple в последний раз забирала ваш файл.
Последний пункт объясняет большинство ситуаций «я всё починил, а ничего не изменилось». После установки телефон перепроверяет файл примерно раз в неделю. Чтобы проверить исправление сразу, переустановите приложение. Для staging добавьте ?mode=developer к записи applinks: так CDN пропускается, но только для сборок с подписью разработчика и только на устройствах, где вы это включили.
Цифры, которые стоит запомнить
- столько CDN Apple хранил рабочий файл в наших тестах
- 6 ч
- столько он хранил ошибку
- 1 ч
- как часто iPhone перепроверяет файл после установки
- ~1 неделя
- минимальное ожидание на Android перед проверкой верификации
- 20 с
столько CDN Apple хранил рабочий файл в наших тестах
столько он хранил ошибку
как часто iPhone перепроверяет файл после установки
минимальное ожидание на 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Что означает каждое состояние
verified
Домен прошёл проверку. Если ссылки всё равно открывают браузер, смотрите на intent filter: android:autoVerify="true", категория BROWSABLE и обе схемы, http и https.
none
Пока ничего не записано. Подождите несколько минут и снова запустите verify-app-links.
legacy_failure
Устаревший верификатор отклонил домен и не объяснил почему. Начните с самого файла: HTTP 200, application/json, HTTPS, без редиректов.
1024 и выше (например, 1026)
Ошибка конкретного верификатора. Документация Android отсылает к сети и хостингу: всё те же правила про 200, JSON, HTTPS и отсутствие редиректов.
approved / denied
Выставлено shell-командой, а не верификацией. Сбросьте через set-app-links, прежде чем доверять любому результату.
migrated / restored / system_configured
Перенесено из устаревшей верификации, восстановлено вместе с данными пользователя или задано конфигурацией устройства. Это не ошибки, но и не доказательство, что ваш файл работает сегодня.
Отпечаток, который верен на ноутбуке и неверен в Play Store
Самая частая поломка на Android вообще не связана с хостингом. При Play App Signing Google заново подписывает ваше приложение своим ключом подписи. SHA-256, который keytool выдаёт для вашего ключа загрузки, — не тот, что стоит на телефонах пользователей, поэтому релизная сборка не проходит, а локальная проходит.
Берите отпечаток в 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"Пока вы чините, кампании работают
Сломанные файлы связки не должны стоить вам установок. Ссылка Appy на любом тарифе отправляет каждый телефон в нужный стор, включая Huawei AppGallery, а на Pro сначала пробует открыть ваше приложение, так что те, у кого оно уже есть, попадают прямо в него. Без файла AASA, без SDK, без нового релиза. Когда Universal Links снова заработают, оставьте ту же ссылку Appy: напечатанные коды и посты менять не придётся.
appy.to/yourapp
работает, пока вы отлаживаете
- iPhoneВаше приложение на Pro или App Store
- AndroidВаше приложение на Pro или Google Play
- HuaweiAppGallery
- КомпьютерВаш сайт
Что почитать дальше
- Валидатор Universal LinksЗа один раз проверяет ваш AASA на вашем сервере и в CDN Apple, а заодно assetlinks.json.
- Генератор AASA и assetlinks.jsonСоздаёт оба файла по Team ID, bundle ID и SHA-256.
- Universal Links открывают Safari вместо приложенияПричины на уровне поведения: от правила одного домена до выбора пользователя.
- Android App Links не проходят верификациюПодробный разбор Android-стороны.
Вопросы о кодах ошибок
Где увидеть коды SWCERR?
В заголовке Apple-Failure-Reason при запросе к https://app-site-association.cdn-apple.com/a/v1/your-domain, в выводе swcutil dl на Mac и в логе swcd на устройстве.
Как заставить Apple подхватить исправленный файл AASA?
Сбросить кэш CDN Apple нельзя. CDN заново забирает файл, когда истекает кэш; для ошибок в наших тестах это был один час. Затем переустановите приложение на тестовом телефоне, чтобы он загрузил новую копию, а не ждал еженедельной проверки.
Есть ли инструмент, который проверяет всё это сразу?
Да. Валидатор Universal Links от Appy бесплатный и работает без регистрации. Он проверяет ваш файл AASA на вашем сервере и в CDN Apple, а assetlinks.json через Digital Asset Links API от Google, и подсказывает, что исправить.
Есть ли ограничение на размер файла apple-app-site-association?
В 2016 году Apple указывала лимит в 128 КБ. В текущей документации его нет, но если держать файл компактным, вопрос не возникнет.
Почему ссылка открывает браузер, когда я ввожу её в Safari?
Так и задумано. Введённые вручную URL и ссылки внутри одного домена по замыслу остаются в браузере. Проверяйте из Заметок или Сообщений.
Что означает legacy_failure на Android?
Устаревший верификатор отклонил домен, а Android не говорит почему. Проверьте, что assetlinks.json отдаётся с кодом 200 как application/json по HTTPS без редиректов и что в нём есть отпечаток Play App Signing.
Можно ли обойтись без всего этого?
Отчасти. На тарифе Pro ссылка Appy сначала пробует URL-схему вашего приложения, а если не вышло, ведёт в нужный стор, поэтому работает без файлов AASA на вашем домене. Для настоящих Universal Links всё равно нужна настройка, описанная выше.
Продолжить изучение
Android App Links не проходят проверку: диагностика за пять минут с adb
С Android 12 App Link, не прошедший проверку домена, открывается в браузере вместо приложения — молча и не на всех устройствах. adb-чеклист, который быстро находит причину.
Universal Links открывают Safari? Исправьте AASA, App Links, редиректы и headers
Практичный troubleshooting-процесс для исправления universal links и app links, открывающих браузер вместо приложения.
Как встроенные браузеры обрабатывают диплинки: Instagram, TikTok, Facebook, Gmail, Telegram и другие
Из Safari ссылка открывает приложение, а внутри Instagram не работает. Разбираем, какой браузер использует каждое приложение, какие правила задают Apple, Google и Chrome и что с этим можно сделать.
Ищете другое? Посмотрите все темы в блоге.
Хватит терять нажатия из-за сломанных ссылок
Найдите сломанный файл бесплатным валидатором, а пока чините, пусть кампании работают через ссылку Appy: нужный стор на любом тарифе, ваше приложение на Pro.