Skip to content

fix: SDXL model crash on iOS - use correct pipeline type - #88

Merged
alichherawalla merged 1 commit into
mainfrom
fix/sdxl-crash
Mar 1, 2026
Merged

alichherawalla merged 1 commit into
mainfrom
fix/sdxl-crash

Conversation

@alichherawalla

Copy link
Copy Markdown
Collaborator

Summary

Fixes iOS crash when loading/generating with SDXL image models. The app was always using StableDiffusionPipeline for all CoreML models, but SDXL models require StableDiffusionXLPipeline. The regular pipeline's TextEncoder expects an output feature named last_hidden_state, but SDXL's TextEncoder outputs hidden_embeds — causing a nil force-unwrap crash at TextEncoder.swift:89.

Now detects SDXL models by checking for TextEncoder2.mlmodelc in the model directory and creates the appropriate pipeline type.

Also bumps version to 0.0.61 for both platforms.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Screenshots / Screen Recordings

N/A — no UI changes, fix is in native pipeline selection logic.

Checklist

General

  • My code follows the project's coding style and conventions
  • I have performed a self-review of my code
  • I have added/updated comments where the logic isn't self-evident
  • My changes generate no new warnings or errors

Testing

  • I have tested on Android (physical device or emulator)
  • I have tested on iOS (physical device or simulator)
  • I have tested in light mode and dark mode
  • Existing tests pass locally (npm test)
  • I have added tests that prove my fix is effective or my feature works

React Native Specific

  • No new native module without corresponding platform implementation (Android + iOS)
  • New native modules are added to the Xcode project build target (project.pbxproj)

Security

  • No secrets, API keys, or credentials are included in the code

Additional Notes

  • Root cause: StableDiffusionPipeline uses TextEncoder which looks for output "last_hidden_state". SDXL TextEncoder outputs "hidden_embeds" instead. The library already has StableDiffusionXLPipeline with TextEncoderXL that handles this correctly — we just weren't using it.
  • Both pipeline types conform to StableDiffusionPipelineProtocol, so the rest of the code (generate, unload, etc.) works unchanged.
  • SD 1.5 and SD 2.1 models (palettized and full precision) are unaffected.

…bump to 0.0.61

SDXL models crashed on iOS because CoreMLDiffusionModule always created
StableDiffusionPipeline, which uses TextEncoder expecting "last_hidden_state"
output. SDXL TextEncoder outputs "hidden_embeds" instead, causing a nil
force-unwrap crash. Now detects SDXL models by checking for TextEncoder2.mlmodelc
and creates StableDiffusionXLPipeline accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@alichherawalla
alichherawalla merged commit 6433a41 into main Mar 1, 2026
4 checks passed
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a crucial fix for iOS users experiencing crashes when interacting with SDXL image models. By introducing dynamic pipeline selection based on model type, the application now correctly handles both standard and SDXL models, preventing runtime errors and improving stability. The change ensures that the correct underlying CoreML pipeline is utilized, addressing a fundamental incompatibility without altering the user interface or core generation flow. Additionally, the application's version has been incremented to reflect these updates.

Highlights

  • iOS SDXL Model Crash Fix: Resolved a critical crash on iOS when loading or generating with SDXL image models. The issue stemmed from using the incorrect StableDiffusionPipeline for SDXL models, which require StableDiffusionXLPipeline due to differences in TextEncoder output expectations.
  • Dynamic Pipeline Selection: Implemented logic to dynamically detect SDXL models by checking for the presence of TextEncoder2.mlmodelc and instantiate the appropriate pipeline (StableDiffusionXLPipeline or StableDiffusionPipeline) to ensure compatibility.
  • Version Bump: Updated the application version to 0.0.61 across both Android and iOS platforms.
Changelog
  • android/app/build.gradle
    • Updated versionCode from 1772365762 to 1772374541.
    • Updated versionName from "0.0.60" to "0.0.61".
  • ios/CoreMLDiffusionModule.swift
    • Changed the pipeline property type from StableDiffusionPipeline? to StableDiffusionPipelineProtocol? to support polymorphism.
    • Added a private helper function isXLModel(at:) to detect SDXL models by checking for TextEncoder2.mlmodelc.
    • Modified the loadModel function to conditionally initialize either StableDiffusionXLPipeline or StableDiffusionPipeline based on the detected model type.
    • Updated the type of pipelineConfig from StableDiffusionPipeline.Configuration to PipelineConfiguration for broader compatibility.
  • ios/OffgridMobile.xcodeproj/project.pbxproj
    • Updated CURRENT_PROJECT_VERSION from 1772365762 to 1772374541 for both debug and release configurations.
    • Updated MARKETING_VERSION from 0.0.60 to 0.0.61 for both debug and release configurations.
  • package.json
    • Updated the version field from "0.0.60" to "0.0.61".
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@sonarqubecloud

sonarqubecloud Bot commented Mar 1, 2026

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly fixes a crash on iOS when using SDXL models by introducing logic to detect the model type and instantiate the appropriate pipeline (StableDiffusionXLPipeline for SDXL, StableDiffusionPipeline for others). The change to use the StableDiffusionPipelineProtocol is a good approach to handle different pipeline implementations. The version numbers are also consistently updated across platforms. My main feedback is a suggestion to refactor the pipeline creation logic into a separate helper function to improve code organization and maintainability.

Comment on lines +69 to +84
if self.isXLModel(at: url) {
// SDXL models need the XL pipeline which uses TextEncoderXL
// (expects "hidden_embeds" output instead of "last_hidden_state")
pipe = try StableDiffusionXLPipeline(
resourcesAt: url,
configuration: config,
reduceMemory: true
)
} else {
pipe = try StableDiffusionPipeline(
resourcesAt: url,
controlNet: [],
configuration: config,
reduceMemory: true
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This conditional logic for creating the pipeline is correct. For better code organization and to improve the readability of loadModel, consider extracting this logic into a separate private factory method. This would encapsulate the details of pipeline creation and make the loadModel function's primary responsibility clearer.

For example, you could introduce a method like this:

private func createPipeline(for url: URL, with config: MLModelConfiguration) throws -> StableDiffusionPipelineProtocol {
    if isXLModel(at: url) {
        // SDXL models need the XL pipeline
        return try StableDiffusionXLPipeline(
            resourcesAt: url,
            configuration: config,
            reduceMemory: true
        )
    } else {
        return try StableDiffusionPipeline(
            resourcesAt: url,
            controlNet: [],
            configuration: config,
            reduceMemory: true
        )
    }
}

And then call it from loadModel:

let pipe = try self.createPipeline(for: url, with: config)

This change would make the code more modular and easier to extend if more pipeline types are added in the future.

alichherawalla added a commit that referenced this pull request Oct 22, 2026
Points pro at its release/stable-v55-v115 tip, which adds the shared list-clipping props to
the MCP tool lists and the Sync list. It also brings pro's release-branch merges #88, #89
and #91.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant