Fix: dyld: Library not loaded Reason: image not found in Xcode

Fix: dyld: Library not loaded Reason: image not found in Xcode

Written by

in

Quick answer: This crash occurs when your app links against a dynamic framework but fails to embed it into the final app bundle. To fix it, select your app target in Xcode, navigate to the General tab, locate Frameworks, Libraries, and Embedded Content, and ensure the framework is set to ‘Embed & Sign’.

Why this happens

When your app launches on a physical iOS device or simulator, the dynamic linker (dyld) inspects your compiled executable to resolve all dynamic libraries and frameworks specified in the Mach-O load commands. If your binary lists a dynamic framework under @rpath/YourFramework.framework/YourFramework, dyld searches the directories listed in your application’s runpath search paths.

If the framework exists at compile time, Xcode successfully links your code against the framework’s headers and symbols. However, linking only guarantees that symbols match during build time. At launch time, if the physical .framework directory is missing from your app bundle’s Frameworks folder, dyld halts execution and crashes immediately with dyld: Library not loaded: @rpath/... Reason: image not found.

This discrepancy often appears when developers add a custom framework to Link Binary With Libraries but forget to embed it in the app bundle. It can also happen when switching between simulator and device builds, when code signing issues prevent the system from loading the embedded binary, or when the Runpath Search Paths (LD_RUNPATH_SEARCH_PATHS) build setting is missing the standard runtime search locations.

How to fix it

1. Set the Framework to Embed & Sign

The most common cause is linking against a dynamic framework without copying it into the compiled application bundle.

  1. Open your project in Xcode and select your main app target in the left sidebar.
  2. Navigate to the General tab.
  3. Scroll down to the Frameworks, Libraries, and Embedded Content section (labeled Embedded Binaries in legacy Xcode versions).
  4. Locate your framework in the list. If it is missing, click the + button and select your framework.
  5. In the Embed column next to your framework, click the dropdown menu and change it from Do Not Embed to Embed & Sign.
Frameworks, Libraries, and Embedded Content
---------------------------------------------------------------
Name                          | Embed
---------------------------------------------------------------
YourFramework.framework       | Embed & Sign
  1. Clean your build folder by pressing Command + Shift + K.
  2. Build and run your app on the physical device.

Selecting Embed & Sign instructs Xcode to run an internal copy-files build phase that places the framework into YourApp.app/Frameworks/ and re-signs it with your development identity, ensuring dyld finds and validates it at launch.

2. Verify Runpath Search Paths in Build Settings

If the framework is embedded inside YourApp.app/Frameworks/ but dyld still reports that @rpath cannot find the image, your app’s executable may not know where @rpath points.

  1. Select your app target in Xcode and open the Build Settings tab.
  2. Ensure All and Combined filters are selected at the top.
  3. Type Runpath Search Paths into the search bar (LD_RUNPATH_SEARCH_PATHS).
  4. Inspect the values assigned to this setting. For an iOS target, verify that the following paths exist:
LD_RUNPATH_SEARCH_PATHS = (
    "$(inherited)",
    "@executable_path/Frameworks"
);

If you are running unit test targets or extensions, ensure the relevant host path is also present (for example, @loader_path/Frameworks). Without @executable_path/Frameworks, dyld has no instruction to look inside the app’s internal Frameworks directory when expanding @rpath.

3. Change Mach-O Type to Static Library (Alternative)

If your custom framework does not need to be a separate dynamic library, you can compile it as a static library. Static frameworks are compiled directly into your app’s main executable binary during the linking phase, eliminating dynamic lookup by dyld entirely.

  1. In your Xcode workspace, select the custom framework’s target.
  2. Go to Build Settings and search for Mach-O Type (MACH_O_TYPE).
  3. Change the value from Dynamic Library to Static Library.
  4. Return to your main app target’s General tab.
  5. Under Frameworks, Libraries, and Embedded Content, change the framework’s embed setting to Do Not Embed (or ensure it is only present in Link Binary With Libraries under Build Phases).
// Mach-O Setting in Custom Framework Target:
Mach-O Type = Static Library

Note: If your framework contains asset catalogs, storyboards, or bundled files, static libraries cannot store resources directly. You must ship those assets in a separate .bundle directory and load them via Bundle(url:) or Bundle(for:) in Swift.

4. Resolve Code Signing Mismatches on Physical Devices

Dynamic libraries embedded in iOS applications must be signed with a provisioning profile and certificate that match the host application. If you build and run fine on the iOS Simulator but crash immediately on a physical iPhone with dyld: Library not loaded, a code-signing validation error is often the culprit.

  1. Open your target’s Build Phases tab.
  2. Expand the Embed Frameworks phase.
  3. Ensure the checkbox for Code Sign On Copy is selected for all custom dynamic frameworks.
  4. If you manage dependencies via Swift Package Manager or Carthage, delete your DerivedData directory to clear stale binary artifacts:
rm -rf ~/Library/Developer/Xcode/DerivedData
  1. In Xcode, select Product > Clean Build Folder (Shift + Command + K), disconnect and reconnect your device, and build again.

How to prevent it

  • Whenever you drag a local .framework or .xcframework into an Xcode project, always verify its status under Frameworks, Libraries, and Embedded Content instead of relying solely on the Link Binary With Libraries build phase.
  • Prefer using Swift Packages (SPM) or modern .xcframework archives rather than raw, single-architecture .framework builds.
  • Keep your target’s Runpath Search Paths set to inherit default values ($(inherited) and @executable_path/Frameworks) rather than overwriting them with hardcoded local directories.
  • Avoid marking dynamic frameworks as Optional in Link Binary With Libraries to suppress missing-binary warnings, as this only delays the crash until code from that module is called.

FAQ

Why does the app work on the simulator but crash on a physical device?

The macOS host running the iOS Simulator can sometimes locate frameworks through fallback developer paths or loose sandbox enforcement that does not strictly check bundle signatures. Physical devices enforce strict sandboxing and code-signing boundaries; if an embedded binary is missing from the bundle or unsigned, dyld terminates the process immediately.

What is the difference between “Embed & Sign” and “Embed Without Signing”?

“Embed & Sign” copies the framework into your .app bundle and re-applies your development or distribution certificate so the framework matches the host app’s entitlements. “Embed Without Signing” leaves existing cryptographic signatures untouched, which is only valid for pre-signed system frameworks or binaries that explicitly prohibit re-signing.

What does @rpath actually mean in the error message?

@rpath stands for Runpath Search Path. It is an environment variable embedded inside the binary that allows a dynamic library to specify that its location is relative to search directories defined by the calling application (via LD_RUNPATH_SEARCH_PATHS), rather than relying on a hardcoded absolute disk path.

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.