ITMS-90683: исправить Missing purpose string в Expo
Автор: Mehdi Azizi
Опубликовано , 6 мин
ITMS-90683 Missing purpose string: почему Apple отклоняет билд, какой ключ добавить в app.json в Expo и как найти недостающие ключи до отправки.
ITMS-90683 это автоматический отказ Apple: он приходит на почту вскоре после отправки билда, ещё до любой ручной проверки. Он значит, что в твоём файле Info.plist нет фразы, которая объясняет, зачем приложению доступ к чувствительным данным. Исправление занимает два шага: добавить ключ, указанный в сообщении, в ios.infoPlist, а потом пересобрать билд.
Я поймал его на Solys, моём будильнике с мини-играми, причём из-за данных, которые приложение даже не использует. Вот что значит это сообщение, почему оно прилетает и как его избежать.
Что значит ошибка ITMS-90683?
Полное сообщение называется «ITMS-90683: Missing purpose string in Info.plist». Оно говорит, что код твоего приложения ссылается на API, которое работает с чувствительными данными (фото, камера, микрофон, геопозиция, контакты), а в твоём Info.plist нет соответствующего ключа описания. Сообщение называет этот ключ, например NSPhotoLibraryUsageDescription.
Эта фраза-описание называется «purpose string». Это текст, который iOS показывает в окне запроса разрешения. Apple пишет об этом в документации про доступ к защищённым ресурсам: App Review отклоняет приложения, код которых обращается к этим ресурсам без purpose string.
Это не отказ ревьюера. Проверка автоматическая и срабатывает при загрузке билда, до отправки на ревью, как ITMS-91053 для манифеста конфиденциальности. Билд отбраковывается, и нужно отправить новый.
Почему Apple отказывает, хотя приложение не использует эти данные
Вот что удивляет. Apple анализирует код внутри билда, а не то, что приложение реально делает. Если библиотека, которую ты подключаешь, содержит ссылку на фототеку, ключ обязателен, даже если ни один экран никогда не запрашивает доступ к фото. Сообщение Apple само это уточняет: внешняя библиотека или SDK может ссылаться на эти API, и purpose string всё равно обязательна.
Мой случай, 26 сентября 2026 года. Пока я чистил конфигурацию Solys, я удалил ключ NSPhotoLibraryUsageDescription, ведь приложение не трогает никакие фото. Следующий билд отклонили с ITMS-90683. Причина: две библиотеки Expo, которые использует приложение, expo-image и expo-file-system, содержат код со ссылкой на фототеку. Предыдущий билд проходил, потому что ключ ещё был на месте.
Урок: ключ описания не удаляют «потому что он не нужен». Его удаляют, только когда ни одна библиотека в билде больше не ссылается на это API.
Самые частые ключи
NSPhotoLibraryUsageDescription: чтение или запись фото.NSPhotoLibraryAddUsageDescription: добавление фото без чтения.NSCameraUsageDescription: камера.NSMicrophoneUsageDescription: микрофон.NSLocationWhenInUseUsageDescription: геопозиция во время использования.NSContactsUsageDescription: контакты.NSUserTrackingUsageDescription: рекламное отслеживание (App Tracking Transparency).
Apple описывает каждый ключ в документации, например NSPhotoLibraryUsageDescription: он обязателен, как только приложение использует API, которое читает фототеку или пишет в неё.
Как исправить ITMS-90683 в приложении на Expo
- Выпиши ключ, указанный в письме Apple. В сообщении есть его точное имя.
- Добавь его в конфигурацию в
ios.infoPlist, как описано в документации Expo о разрешениях:
{
"expo": {
"ios": {
"infoPlist": {
"NSPhotoLibraryUsageDescription": "Solys не получает доступ к твоим фото. Это разрешение никогда не запрашивается."
}
}
}
}
- Пересобери билд. Expo это уточняет: изменение Info.plist не доставляется удалённым обновлением, нужен новый бинарник.
- Отправь билд в Apple заново, затем выбери его в своей версии.
Ловушка, если приложение локализовано: языковые файлы переводят ключ, но не объявляют его. Ключ сначала должен существовать в ios.infoPlist (или в конфигурации соответствующего плагина). Иначе приложение может упасть при первом вызове.
Какую фразу писать, если приложение не использует эти данные?
Apple требует точное, полезное и конкретное описание. Если приложение действительно использует данные, скажи одной фразой, зачем: «Приложение использует камеру, чтобы сканировать штрихкод твоего билета.»
Если ключ нужен только из-за библиотеки, Apple даёт два варианта: написать фразу или убрать код, который обращается к данным. Когда этот код из библиотеки, просто так его не уберёшь. Поэтому для Solys я написал правду: «Solys не получает доступ к твоим фото. Это разрешение никогда не запрашивается.» Это прагматичный выбор: следующий билд прошёл загрузку, но обещать, что Apple всегда примет такую фразу, я не могу.
Как найти недостающие ключи до отправки
Из корня проекта эта команда выводит файлы библиотек, чей iOS-код ссылается на самые контролируемые API:
grep -rlE "PHPhotoLibrary|AVCaptureDevice|CLLocationManager|CNContactStore|EKEventStore|ATTrackingManager" \
node_modules/*/ios node_modules/@*/*/ios
Каждое имя соответствует типу данных: PHPhotoLibrary для фото, AVCaptureDevice для камеры и микрофона, CLLocationManager для геопозиции, CNContactStore для контактов, EKEventStore для календаря, ATTrackingManager для отслеживания. Для каждого результата проверь, что нужный ключ описания есть в твоей конфигурации.
Эта страховка ловит случаи, с которыми я сталкивался. Она не заменяет чтение письма Apple, которое остаётся единственным надёжным списком, как и для непубличных API в ITMS-90338. После того отказа я делаю эту проверку перед каждым билдом: она занимает несколько секунд, а отказ ITMS-90683 стоит билда и времени на его пересборку.
Отправить билд без неприятных сюрпризов
ITMS-90683 исправляется быстро, если знаешь, как его читать, так же как ITMS-90725, который касается версии Xcode. Отказы, которые приходят потом, уже от ревьюера, требуют больше вдумчивости: порядок действий описан на странице приложение отклонено Apple, а самые частые причины в статье почему Apple отклоняет приложение.
Чтобы проверить всё перед отправкой, в Apple Review Kit собраны мой чеклист и skills для Claude Code, которые просматривают твой проект. Если отправка застряла и нужен живой взгляд, забронируй час со мной: разберём твой проект по видеосвязи, прямо на твоём экране. А если готовишь первый релиз, пройди бесплатную диагностику: она расставит шаги по порядку и пришлёт тебе мой чеклист против отказов Apple.
Частые вопросы
ITMS-90683 это отказ App Review?
Не в смысле живого ревьюера. Это автоматическая проверка билда при загрузке, до отправки на ревью, как ITMS-90717 для иконки. Никто твоё приложение не открывал. Билд отбракован: нужно исправить Info.plist и отправить новый.
Почему Apple требует ключ для данных, которые моё приложение не использует?
Потому что Apple анализирует код в билде, а не поведение приложения. Если встроенная библиотека ссылается на фототеку или камеру, ключ описания обязателен, даже если ни один экран никогда не запрашивает этот доступ.
Можно ли исправить ITMS-90683 удалённым обновлением?
Нет. Недостающий ключ находится в Info.plist, а он часть бинарника. Удалённое обновление этот файл не меняет: нужно пересобрать билд и снова отправить его в Apple.
Куда добавить NSPhotoLibraryUsageDescription в проекте Expo?
В конфигурацию приложения, в ios.infoPlist, с фразой, которая описывает использование. Некоторые библиотеки также предлагают отдельную настройку в своём плагине, которая может добавлять и другие ключи, например фоновый режим. В обоих случаях ключ должен быть в основной конфигурации, а не только в файлах перевода.
Нужно ли удалять неиспользуемые ключи описания?
Только если ни одна библиотека в билде больше не ссылается на соответствующее API. Иначе следующую отправку отклонят с ITMS-90683. Прежде чем удалять ключ, поищи имя API в iOS-коде своих зависимостей.