Решение: CocoaPods could not find compatible versions for pod при сборке Flutter под iOS
Читайте вторую строку ошибки, а не первую. Именно она называет причину: устаревший Podfile.lock, слишком низкий deployment target или два плагина, фиксирующих один транзитивный pod.
Решение целиком зависит от строки прямо под ошибкой, и вариантов всего четыре. Если там In snapshot (Podfile.lock), удалите ios/Podfile.lock и выполните pod install. Если там сказано, что спецификации required a higher minimum deployment target, поднимите platform :ios в вашем Podfile. Если перечислены два плагина, каждый из которых разрешается в свою точную версию одного и того же pod, это настоящий конфликт, и чинится он в pubspec.yaml, а не в Podfile. Только четвёртый случай, действительно устаревший репозиторий спецификаций, лечится командой pod repo update. Запуск pod repo update первым делом, что делает почти каждый, тратит две минуты в тех трёх случаях, где он помочь не может.
Статья написана для Flutter 3.44.7 (stable, июль 2026), CocoaPods 1.17.0 (выпущен 2026-07-06), Dart 3.12 и Xcode 16.x на macOS Sequoia.
Ошибка в контексте
Самая частая форма, возникающая сразу после flutter pub upgrade, поднявшего плагин Firebase:
[!] CocoaPods could not find compatible versions for pod "Firebase/CoreOnly":
In snapshot (Podfile.lock):
Firebase/CoreOnly (= 10.28.0)
In Podfile:
firebase_core (from `.symlinks/plugins/firebase_core/ios`) was resolved to 3.4.0, which depends on
Firebase/CoreOnly (= 11.0.0)
You have either:
* out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
* changed the constraints of dependency `Firebase/CoreOnly` inside your development pod `firebase_core`.
You should run `pod update Firebase/CoreOnly` to apply changes you've made.
Error running pod install
Error launching application on iPhone 16 Pro.
Вторая форма, которая выглядит той же ошибкой, но ею не является:
[!] CocoaPods could not find compatible versions for pod "sqflite_darwin":
In Podfile:
sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
Specs satisfying the `sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)` dependency were
found, but they required a higher minimum deployment target.
Обе начинаются с одной и той же заголовочной строки, и именно поэтому результаты поиска по этой ошибке представляют собой мешанину противоречивых советов. Дальше первой строки у них нет ничего общего.
Почему CocoaPods сообщает об этом вместо того, чтобы просто выбрать версию
CocoaPods разрешает зависимости через Molinillo, решатель с возвратом в стиле SAT. Ему передают набор ограничений и просят найти по одной версии каждого pod, которая удовлетворяет им всем одновременно. Исчерпав пространство поиска без решения, он не гадает. Он печатает ограничения, которые оставались в конфликте на момент отказа, плюс шаблонный список причин, иногда вызывающих конфликты.
Этот список шаблонный в буквальном смысле. Он печатается независимо от того, применим он или нет. Диагностическое содержимое находится в блоке с отступом выше него, где названо каждое ограничение и его источник. Невыполнимое ограничение в этот набор помещают четыре вещи:
Podfile.lockфиксирует старую точную версию. Файл блокировки участвует в разрешении как ограничение с пометкойIn snapshot (Podfile.lock). Обновление плагина на стороне Dart изменило требования podspec, а блокировка продолжает настаивать на старом номере. С большим отрывом самая частая причина.- Всем версиям-кандидатам нужен более высокий deployment target, чем объявлен в вашем
Podfile. Molinillo отфильтровывает спецификации, у которыхdeployment_targetпревышает вашу строку платформы, а затем сообщает о пустом наборе кандидатов. Это вариантrequired a higher minimum deployment target. - Два плагина фиксируют несовместимые точные версии общего транзитивного pod. Настоящий ромб зависимостей. Никакая правка
Podfileего не решает, потому что ограничение исходит из двух podspec, которые Flutter сгенерировал из вашегоpubspec.yaml. - Репозиторий спецификаций старше запрашиваемой версии. Актуально, только если вы используете репозиторий спецификаций на базе git. CDN-источник, который использует стандартный
Podfileот Flutter, вpod repo updateне нуждается.
Минимальное воспроизведение
Случай 1 воспроизводится тремя командами в любом проекте с плагином, у которого зафиксирована нативная зависимость:
# Flutter 3.44.7, CocoaPods 1.17.0
flutter create podconflict && cd podconflict
flutter pub add firebase_core:3.1.0 && (cd ios && pod install)
flutter pub add firebase_core:3.4.0 && (cd ios && pod install) # boom
Первый pod install записывает Firebase/CoreOnly (= 11.0.0) в ios/Podfile.lock. Второй flutter pub add меняет плагин на тот, чей podspec требует другую точную версию, и ограничение из файла блокировки становится невыполнимым относительно нового podspec.
Случай 2 воспроизводится понижением строки платформы ниже того, что нужно плагину:
# ios/Podfile -- Flutter 3.44.7, CocoaPods 1.17.0
platform :ios, '12.0'
с плагином, чей podspec объявляет:
# .symlinks/plugins/sqflite_darwin/darwin/sqflite_darwin.podspec
s.platform = :ios, '13.0'
Решение по порядку приоритета
1. Если в ошибке есть In snapshot (Podfile.lock), удалите блокировку
Файл блокировки представляет собой кеш предыдущего разрешения, а не источник истины. Flutter при каждой сборке заново строит весь граф pod из pubspec.lock, поэтому ios/Podfile.lock, расходящийся с ним, по определению устарел и авторитетом не является.
# Flutter 3.44.7, CocoaPods 1.17.0 -- run from the repo root
flutter pub get
cd ios
rm Podfile.lock
pod install
Обратите внимание на порядок. flutter pub get должен выполняться первым, поскольку именно он переписывает ios/.symlinks/plugins/, чтобы каталог указывал на разрешённые версии плагинов в кеше pub. Запуск pod install до него разрешает podspec тех версий плагинов, что лежали там в прошлый раз, что даёт ту же ошибку с другими числами и отправляет вас по кругу.
Если плагин ваш собственный или вам нужна точечная правка вместо полного пересчёта:
# CocoaPods 1.17.0 -- surgical alternative, keeps other pins intact
cd ios && pod update Firebase/CoreOnly
В приложении на Flutter предпочтительнее удалить блокировку. pod update <pod> уместен в написанном вручную iOS-проекте, где файл блокировки кодирует осознанные фиксации; в приложении на Flutter эти фиксации пришли из pubspec.lock, и оттуда же они должны приходить дальше.
2. Если в ошибке есть higher minimum deployment target, поднимите платформу в двух местах
Это нужно и Podfile, и проекту Xcode. Правка только Podfile чинит разрешение pod, а затем падает позже на этапе компоновки, потому что собственная настройка сборки цели Runner всё ещё объявляет старую нижнюю границу.
# ios/Podfile -- Flutter 3.44.7
platform :ios, '15.0'
# ios/Podfile -- force every pod target to inherit the same floor
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
end
end
end
Затем задайте то же и для цели приложения. Откройте ios/Runner.xcworkspace, выберите цель Runner, перейдите в Build Settings и установите iOS Deployment Target в то же значение для Debug и Release. Для самого Runner настройка workspace побеждает Podfile; строка в Podfile управляет только целями pod.
Не подбирайте число перебором. Считайте его из podspec, на котором произошёл сбой:
# Flutter 3.44.7 -- print the floor the failing plugin actually declares
grep -r "s.platform\|deployment_target" ios/.symlinks/plugins/sqflite_darwin/darwin/*.podspec
Поднятие нижней границы отсекает старые устройства, поэтому поднимайте ровно до того, что требует podspec, а не до самой новой установленной у вас версии iOS.
3. Если два плагина фиксируют один pod на разные точные версии, правьте pubspec.yaml
Это тот случай, когда любая правка Podfile и любая очистка кеша бесполезны, потому что конфликт лежит выше CocoaPods. Признак: две строки was resolved to, называющие два разных плагина:
[!] CocoaPods could not find compatible versions for pod "GTMSessionFetcher/Core":
In Podfile:
firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) was resolved to 5.1.0, which depends on
GTMSessionFetcher/Core (~> 3.3)
google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`) was resolved to 5.7.6, which depends on
GTMSessionFetcher/Core (< 3.0, >= 1.1)
~> 3.3 и < 3.0 не пересекаются. Найдите версии плагинов, чьи podspec согласуются между собой, и зафиксируйте их в pubspec.yaml:
# pubspec.yaml -- Flutter 3.44.7, Dart 3.12
dependencies:
firebase_auth: ^5.1.0
google_sign_in: ^6.2.2 # 6.2.2 ships google_sign_in_ios 5.7.7+, which allows GTMSessionFetcher 3.x
Затем пересчитайте оба слоя:
# Flutter 3.44.7, CocoaPods 1.17.0
flutter pub get
cd ios && rm Podfile.lock && pod install
Вместо этого можно навязать версию транзитивного pod прямо из Podfile:
# ios/Podfile -- last resort, use only to unblock while waiting on a plugin release
pod 'GTMSessionFetcher/Core', '3.4.1'
Считайте это временной заплаткой со сроком годности. Она перекрывает ограничение, которое автор плагина написал намеренно, и сборка будет проходить чисто ровно до того момента, когда приложение упадёт в среде выполнения из-за отсутствующего селектора.
Если сам flutter pub get падает ещё до того, как вы дошли до CocoaPods, у вас проблема разрешения на стороне Dart, а не нативная, и читать нужно другие ограничения: см. почему “Version solving failed” это доказательство, а не баг.
4. И только потом обновляйте репозиторий спецификаций
# CocoaPods 1.17.0
cd ios && pod install --repo-update
Это помогает ровно в одной ситуации: вы используете репозиторий спецификаций на базе git (source 'https://github.com/CocoaPods/Specs.git' в вашем Podfile), и ваш локальный клон старше запрашиваемой версии. Сгенерированный Flutter Podfile по умолчанию использует CDN-источник, который запрашивает версии по HTTP для каждого pod и в этом смысле никогда не устаревает. Если строку source вы не меняли, --repo-update не делает ничего полезного и стоит вам полного клонирования спецификаций.
Подводные камни и похожие ошибки
flutter clean не трогает Podfile.lock. Он очищает build/ и .dart_tool/. ios/Podfile.lock и ios/Pods/ переживают его нетронутыми, поэтому “я уже выполнял flutter clean” остаётся самым частым ложным следом при этой ошибке. Радикальный вариант, который действительно очищает состояние iOS:
# Flutter 3.44.7, CocoaPods 1.17.0
flutter clean
cd ios && pod deintegrate && rm -rf Pods Podfile.lock .symlinks
cd .. && flutter pub get
cd ios && pod install
arch -x86_64 pod install устарел. Этот обходной приём родом из 2021 года, когда у гема ffi не было бинарника под arm64. CocoaPods 1.17.0 на Ruby 3.x работает нативно на Apple Silicon. Префикс arch -x86_64 сегодня принудительно запускает Ruby под Rosetta, где ваши гемы могут быть не установлены, и приводит к совершенно постороннему сбою.
Плагин, перешедший на SwiftPM, в графе pod не появится вовсе. С тех пор как Flutter 3.44 сделал Swift Package Manager значением по умолчанию, плагины, поставляющие Package.swift, разрешаются через SwiftPM, и CocoaPods их никогда не видит. Обычно именно поэтому эта ошибка исчезает после обновления. Это также означает, что конфликт, о котором вы читаете в ответе на StackOverflow от 2024 года, может уже не воспроизводиться, а фиксация pod в вашем Podfile ради плагина, который с тех пор мигрировал, тихо ничего не изменит. Проверьте, какой решатель владеет плагином, прежде чем городить обход:
# Flutter 3.44.7 -- if this file exists, the plugin is on SwiftPM, not CocoaPods
ls ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift
Error running pod install без блока ограничений под ним это другая ошибка. Если раздела с отступом In Podfile: нет, CocoaPods упал до разрешения, обычно из-за проблемы с окружением Ruby или Xcode, а не из-за конфликта версий. Это относится к чек-листу сборки под iOS с Xcode 16, а не сюда.
Воспроизводимость в CI. Хранить ios/Podfile.lock в репозитории правильно по умолчанию, но из-за этого случай 1 срабатывает в CI в первый же раз, когда кто-то в команде поднимает плагин, не выполнив pod install локально. Либо требуйте, чтобы оба файла блокировки менялись одним коммитом, либо зафиксируйте инструментарий, чтобы сбой был хотя бы детерминированным: см. как нацеливаться на несколько версий Flutter из одного пайплайна CI. Android-сторона того же класса проблем разобрана в сбое assembleDebug с exit code 1.
Срок, о котором стоит знать
Репозиторий спецификаций CocoaPods Trunk окончательно переходит в режим только для чтения 2026-12-02, с репетиционным отключением с 2026-11-01 по 2026-11-07. Существующие pod продолжат разрешаться, а CDN продолжит отдавать файлы, так что сборки не сломаются, но ни один pod больше никогда не опубликует новую версию. На практике: после этой даты случай 3 перестаёт решаться ожиданием. Если два плагина фиксируют несовместимые версии общего pod и ни один из них не выпустит исправленный podspec до декабря, никакой релиз сверху вас уже не спасёт, и остаются только два выхода: переопределение в Podfile или перевод плагина на SwiftPM. Оба стоит закладывать в план сейчас, а не в первом квартале.
Источники
- CocoaPods Trunk read-only plan (блог CocoaPods)
- Swift Package Manager for Flutter app developers (docs.flutter.dev)
- Заметки о выпусках Flutter (docs.flutter.dev)
- Релизы CocoaPods (CocoaPods/CocoaPods)
- flutter/flutter#168660: could not find compatible versions for pod Firebase/CoreOnly (flutter/flutter)
- flutter/flutter#148116: could not find compatible versions for pod GTMSessionFetcher/Core (flutter/flutter)
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.