Fix: Flutter/Flutter.h File Not Found in iOS Xcode Builds

Fix: Flutter/Flutter.h File Not Found in iOS Xcode Builds

Written by

in

Quick answer: This error occurs when CocoaPods fails to resolve the Flutter engine framework path for native plugins. To fix it, delete ios/Flutter/Flutter.podspec, run flutter clean, navigate to your ios folder, run pod install, and rebuild your project.

Why this happens

When you compile a Flutter app for iOS, native plugins (such as shared_preferences or url_launcher) compile as CocoaPods targets. These native plugins depend on the core Flutter engine headers via #import <Flutter/Flutter.h>.

Xcode locates these headers using the CocoaPods dependency graph, which reads build settings generated by Flutter’s CLI tools. The primary connector is ios/Flutter/Flutter.podspec along with environment configurations generated in ios/Flutter/Generated.xcconfig.

If you clone a project onto a new Mac, change Flutter SDK branches, upgrade CocoaPods, or change local path structures, the paths cached in Flutter.podspec and Pods/ become invalid. CocoaPods continues to reference an obsolete engine framework location or an empty framework search path, causing Clang to fail immediately when building any plugin with 'Flutter/Flutter.h' file not found.

How to fix it

1. Remove the cached Flutter.podspec and clean build artifacts

The most common trigger is an outdated or machine-specific Flutter.podspec file stored in your version control or generated by an older Flutter build session. Deleting it forces the Flutter CLI to recreate an accurate spec for your current environment.

Open Terminal at the root of your Flutter project and run:

rm -f ios/Flutter/Flutter.podspec
flutter clean
flutter pub get
cd ios
pod install
cd ..
flutter run

This removes the stale specification, flushes the intermediate compilation files in .dart_tool and build/, and instructs CocoaPods to link plugins against the active engine path defined by your current Flutter SDK.

2. Completely deintegrate and reinstall CocoaPods

If removing Flutter.podspec does not resolve the error, the CocoaPods lockfile and target support files may still contain hardcoded search paths to old framework directories.

Reset your CocoaPods configuration completely:

cd ios
rm -rf Pods Podfile.lock .symlinks
pod deintegrate
pod cache clean --all
cd ..
flutter clean
flutter pub get
cd ios
pod install --repo-update
cd ..

After these commands complete, verify that you build using the generated workspace:

  1. If opening Xcode manually, open ios/Runner.xcworkspace, never ios/Runner.xcodeproj.
  2. In Xcode, check Product > Clean Build Folder (Shift + Command + K).
  3. Run the project from Terminal (flutter run) or directly from Xcode.

3. Verify Framework Search Paths in Build Settings

Sometimes manual project modifications override the search paths that CocoaPods injects. Check your runner target configuration in Xcode:

  1. Open ios/Runner.xcworkspace in Xcode.
  2. Select the top-level Runner project in the Project Navigator, then choose the Runner target.
  3. Navigate to the Build Settings tab and ensure All and Combined filters are active.
  4. Search for Framework Search Paths (FRAMEWORK_SEARCH_PATHS).
  5. Check that the entry includes $(inherited) at the top of the list. If $(inherited) is missing, the target ignores the flags generated by CocoaPods in Pods-Runner.debug.xcconfig, blocking access to Flutter.framework.

4. Reconstruct the iOS project directory

If the project has structural corruption from previous SDK migrations, regenerating the platform files is faster than tracking down broken build flags.

  1. Back up your custom native assets, typically located in ios/Runner/:
    – Assets.xcassets (app icons and launch images)
    – Info.plist (URL schemes, permissions, bundle IDs)
    – GoogleService-Info.plist (if using Firebase)
    – Any custom Objective-C, Swift, or bridging code in ios/Runner/

  2. Delete the ios/ folder:

rm -rf ios
  1. Recreate the iOS scaffolding using the Flutter CLI from your project root:
flutter create --platforms=ios .
  1. Restore your backed-up files into the newly created ios/Runner/ folder.
  2. Open ios/Runner.xcworkspace in Xcode, verify your Bundle Identifier and Signing & Capabilities settings under the Runner target, and run flutter run.

How to prevent it

  • Add ios/Flutter/Flutter.podspec to your project’s .gitignore file. This file is generated dynamically and should not be tracked across different developer machines.
  • Ensure ios/Pods/ and ios/.symlinks/ are always excluded from Git.
  • Avoid opening Runner.xcodeproj directly; always use Runner.xcworkspace when editing native iOS code.
  • Run flutter clean and pod install immediately after switching Flutter channels or upgrading the Flutter SDK.

FAQ

Why does this error happen on a new Mac when the project builds fine on another machine?

The ios/Flutter/Flutter.podspec or CocoaPods lockfiles frequently contain paths tied to the original machine’s username, Flutter SDK directory, or architecture. When checked into version control and cloned onto a new machine, CocoaPods attempts to locate the Flutter headers at the old machine’s file paths.

Should I check the Podfile.lock into version control for Flutter apps?

Yes, ios/Podfile.lock should generally be committed to ensure reproducible plugin builds across team members. However, ephemeral files such as Flutter.podspec, Generated.xcconfig, .symlinks, and the Pods directory itself must remain untracked.

Can running Xcode on an Apple Silicon Mac cause this issue?

Yes. If CocoaPods or terminal sessions run under Rosetta while Flutter runs as native ARM64 (or vice versa), CocoaPods may link architecture-specific slices that fail to locate header modules during compilation. Ensure both your terminal shell and CocoaPods installation match your Mac’s native architecture.

Sources & credits

Parts of this guide are adapted from content licensed under CC BY-SA 4.0; this article is shared under the same license.