TestFlight Build Crashes with Metal API on Apple Vision Full Immersive (VisionOS 2)

Hello Unity Community,

I’ve been struggling with an issue that has been driving us crazy since VisionOS 1, across various Unity and Xcode versions. The problem is not easily reproducible or explainable, making it incredibly frustrating to debug.

I would greatly appreciate any support, insights, or suggestions on how to resolve this issue or any potential approaches to try. Below is a detailed description of the problem:

Environment:

  • Xcode Version: 16.2 (16C5032a)

  • Unity Version: 6000.0.32f1

  • Rendering API: Metal API

  • Apple VisionOS: Version 2

Manifest Dependencies:


"dependencies": {

"com.unity.polyspatial.extensions": "2.1.2",

"com.unity.polyspatial.visionos": "2.1.2",

"com.unity.postprocessing": "3.4.0",

"com.unity.render-pipelines.universal": "17.0.3",

"com.unity.timeline": "1.8.7",

"com.unity.visualeffectgraph": "17.0.3",

"com.unity.visualscripting": "1.9.5",

"com.unity.xr.arkit": "6.0.4",

"com.unity.xr.hands": "1.5.0",

"com.unity.xr.interaction.toolkit": "3.0.7",

"com.unity.xr.management": "4.5.0",

"com.unity.xr.oculus": "4.4.0",

"com.unity.xr.openxr": "1.13.2",

"com.unity.xr.visionos": "2.0.4",

"com.unity.modules.vr": "1.0.0",

"com.unity.modules.wind": "1.0.0",

"com.unity.modules.xr": "1.0.0"

}

Problem Description:

1. TestFlight Crash Reports:

• The app consistently crashes after uploading to TestFlight, even with different configurations (Release, Debug, Internal Testing, App Store Connect).

• Crashes occur in a reproducible but varying manner:

• On app launch.

• During a scene transition to the same scene.

** If I open First Time my App with Debugger attached folowing error appears: **

-[MTLDebugRenderCommandEncoder validateCommonDrawErrors:]:5782: failed assertion `Draw Errors Validation

Vertex Function(xlatMtlMain): missing buffer binding at index 1 for UnityDrawCallInfo[0].

Happens here:

->  0x12e92f0d8 <+404>: bl     0x13584fc44               ; objc_release_x23.stub.island
UnityGfxDeviceWorker (53): signal SIGABRT

But when i close and open again it works fine without error and crash. I just dont unterstand why this happens.

More Frequent Crash Reports:

#3 0x0000000101129134 in DarwinApi::detail::Acquire(UnityClassic::Baselib_SystemSemaphore_Handle, unsigned long long) ()

#3 0x00000001032d458c in UnityClassic::Baselib_SystemSemaphore_Acquire(UnityClassic::Baselib_SystemSemaphore_Handle) ()

2. Xcode Console Logs with Metal Validation Enabled:

• Multiple pipeline-related errors appear:

Error creating the CFMessagePort needed to communicate with PPT.

CCPipelineWrapper.mm(109):CreatePipeline:

Pipeline (render) binary archive lookup failed for 'CC_ApplyStencilVertexFunction': Error Domain=AGXMetalG14G Code=3 "Unable to find function "CC_ApplyStencilFragmentFunction" (render pipeline) in binary archives.

• Additional error:

Presenting a drawable without a device anchor. This drawable won't be presented.

3. Additional Xcode Build Warnings (Repeated Over 1000 Times):

Object file (/Users/XXX/Developer/Xcode/DerivedData/Unity-VisionOS-aoipphxayyfwmnamiclwjueppzby/Build/Products/Debug-xros/il2cpp.a(rqbphvf16r2f.o)) was built for newer platform=11 version (2.2) than being linked (2.0)

• Could this mismatch in platform version contribute to the crashes?

• How can I ensure all object files are built for VisionOS 2.0?

If i Remove the checkbox IL2CPP Workkaround Large EXE then Build fails:

B(l) ARM64 branch out of range (-173686720 max is +/-128MB): from __Z69List_1_Clear_m7E49079DAD42707EE3A2ED381D34C4698166F1C2_gshared_inlineP48List_1_t4F7B76BB9BD900E6739B821022D8663D4627BC11PK10MethodInfo (0x0DAA4844) to __Z18il2cpp_codegen_addIiiEN11pick_biggerIT_T0_E4typeES1_S2_ (0x035008B0) in '__Z69List_1_Clear_m7E49079DAD42707EE3A2ED381D34C4698166F1C2_gshared_inlineP48List_1_t4F7B76BB9BD900E6739B821022D8663D4627BC11PK10MethodInfo' from /Users/sergejnawalnew/Library/Developer/Xcode/DerivedData/Unity-VisionOS-bkollgbobjeqglblgecgfnlsafuo/Build/Products/Debug-xros/libGameAssembly.a(qagn4hx1g4pv.o) for architecture arm64  

4. Non-Reproducible Behavior:

• Occasionally, the app works after repeatedly switching between TestFlight builds and reopening/closing the app.

• Once it works, subsequent TestFlight builds also work, even for new versions.

Steps Already Taken:

  1. Build Optimization: Set to -O0 (None) in Xcode.

  2. Schema Testing: Tried both Release and Debug configurations.

  3. Hardware: Tested exclusively on the same Apple Vision device used during local Xcode builds.

  4. Metal Validation: Enabled, revealing errors in pipeline function lookups and binary archive mismatches.

Questions:

  1. Does anyone have a working combination of Unity, VisionOS 2 plugins, and Xcode for Apple Vision builds?

  2. Could the platform version mismatch in object files ( platform=11 (2.2) vs. linked (2.0)) be the root cause of the issue?

  3. Are there known methods to resolve persistent caching issues on Apple Vision that may interfere with TestFlight builds?

Any insights or suggestions would be greatly appreciated. Thank you!

Hey there! Sorry to hear you’re having trouble. There’s a lot going on here, so I’ll try to reply to each of these issues individually. Some of this is familiar, but some of it is not. In order to properly understand what is going on here, we’ll need to replicate the issue on our end. Have you submitted any bug reports regarding these issues? I know it can be difficult to share your full project due to IP ownership issues or long upload times. But, especially with inconsistent issues like these, it’s almost impossible to help without the genuine project folder. If you’re able to create an isolation project that has the same issues, that can sometimes do the trick. TestFlight builds often don’t include enough information, but they’re better than nothing. If you aren’t able to submit the information through our bug reporter (Help > Report a bug...) it can sometimes work to use a secure file sharing service like Google Drive and sharing a link over DM or however you are comfortable getting the project over to us. I’m here to help however I can!

Now let’s dig into these issues individually…

These validation checks can be disabled in Xcode by clicking the target drop-down, going to Edit Scheme... > Diagnostics and disabling Metal API Validation.

We do our best to ensure that you won’t hit these invalid states in normal operation, but it’s possible to hit edge cases like this with custom shaders. There’s one known issue with MSAA on RenderGraph that results in a metal validation error, but it presents slightly differently, so I don’t think that’s what we’re seeing here.

Usually you hit this kind of thing when Unity tries to bind the wrong type of texture to a shader property, like a texture array where a regular 2D texture is expected. This can happen more often on visionOS in Metal mode because we’re doing stereo rendering on Metal, which sometimes uses a texture array (one slice for each eye) where shaders don’t expect it. This usually isn’t something that you can fix on your end, but it’s important for us to know which shader is responsible, and that’s not very easy to figure out as an end-user. Again, we’ll need a bug report with a repro case to solve this one.

In the meantime, you might be able to work past this issue by disabling API validation in Xcode. This validation isn’t enabled for TestFlight or App Store builds, so I don’t believe it is directly responsible for the crash “in the wild.” That is unless, of course, disabling API validation just leads to a crash in the debugger anyway. Given that your next log snippet is UnityGfxDeviceWorker (53): signal SIGABRT, I’ll wager a guess that this is in fact a real crash.

One more thing to point out, the Metal API Validation setting in Unity player settings is not actually the same as API Validation in Xcode under Edit Scheme... > Diagnostics. I know… it’s confusing. :frowning:

Yeah… that’s a weird one. Software is… complicated. :sweat_smile: It’s possible that some of your code (or asset store/package code) is doing a one-time setup step which caches to disk, or it could be something in Unity internals that I’m not aware of.

It could be taking too long to compile shaders. Some users found that enabling the (somewhat hidden) metalCompileShaderBinary player setting to front-load some of that at Unity build time. That thread actually sounds like a reasonably good match for what you’re seeing.

Unfortunately, this isn’t enough information to go on. This is sounding more and more like the (rather frustrating) “2 second deadline” issue with CompositorServices on visionOS. If your app fails to present a new frame within 2 seconds of the last one, for whatever reason, visionOS kills the app. It’s usually the case that we’re waiting on the GPU worker thread during this time, which is implemented in Unity as a semaphore lock. In other words, we didn’t “crash,” we just took too long, and the OS is telling you this is what was happening at the moment it decided to kill the app. It’s also possible that this is a real crash within Unity code, but you’re likely to see a ton of threads waiting on semaphores anyway since that’s what idle threads look like in Unity.

If this is indeed the cause of the crash, you’ll usually see something in the log like: killing FooBar because it hasn't been sending frames for 2.0s. This can be hard to spot, and may not end up in the issues reported on TestFlight.

This one is new to me. Although a quick Google points at something to do with Apple APIs for managing contacts? Not all of the logs you’ll see are coming from Unity, or even from your app necessarily. I think you can safely ignore this one.

I’m quite familiar with this one. It’s benign, and it’s not us. You’ll see this when running any visionOS application using Metal rendering a bunch of times at startup. It’s annoying, but it’s something we need Apple to solve. Please submit feedback to Apple using their Feedback Assistant app asking to have this warning message fixed or suppressed. I usually end up filtering this one out among any other logs coming from CoreComposite so I can read the log properly.

FWIW, that screenshot :point_up_2: is from a run of the default Xcode project template for metal rendering (Swift app, no Unity) running on a Vision Pro. If you scroll up there’s like 100 of those CCPipelineWrapper.mm(109):CreatePipeline: warnings. :person_shrugging:

Same. It’s an unavoidable warning log we get during certain transitions. If it’s constantly spamming, it usually means your AR Session isn’t running, which can happen if your scene doesn’t have an ARSession object, or if something has gone wrong or unexpectedly stopped the session but you’re still trying to update head pose or otherwise do AR stuff.

3. Additional Xcode Build Warnings (Repeated Over 1000 Times):

Object file (/Users/XXX/Developer/Xcode/DerivedData/Unity-VisionOS-aoipphxayyfwmnamiclwjueppzby/Build/Products/Debug-xros/il2cpp.a(rqbphvf16r2f.o)) was built for newer platform=11 version (2.2) than being linked (2.0)

That’s on us, but there really isn’t a good solution here. We ship a pre-compiled library for our XR plugin, and we have to pick an SDK version. We build against the lowest possible version so as not to artificially require you to build with the latest, and no matter what the version we ship will inevitably fall behind. This used to be fine on earlier iOS SDKs and the like, but Xcode complains about it now. We’ve discussed our options with Apple and “live with the warnings” is our currently best option. It bugs me, too, and I’m hoping we can find a better solve in the future.

Again, this one is benign, albeit annoying.

Nothing is certain, but I’m 99% sure it’s not related to any crashes.

You should be able to install the 2.0 SDK and build against it somewhere in build settings but you may need to use Xcode 16.0 (instead of the latest version). In any case, Apple will reject your app unless it’s built with the latest SDK, so you’re forced to use a mismatched SDK anyway.

You’re doing everything right. It’s just a warning we have to live with. :frowning:

This issue comes from the way our IL2CPP code generation works, and basically boils down to some threshold we cross with “too much C# code.” Just URP code with a little extra will do it for visionOS, which means this workaround is almost always required in practice. Again, it’s annoying but once you set it you can forget it. We’ve discussed a more permanent fix with the IL2CPP team but it never materialized. For now, there shouldn’t be any harm in applying the workaround. I think maybe it means builds are a little slower in theory, but if you consider “doesn’t work” to be “infinitely slow,” it’s a speedup! :sweat_smile:

Yeah… I’ve got no idea on this one. I’m fairly sure it’s something specific to your app, but without being able to repro the issue and pick things apart in the debugger I can only speculate. Again, I come back to my hunch about the 2 second deadline. If something is “warming up” the device to allow it to squeak past some bottleneck in just under 2 seconds, whereas a cold start takes just over 2 seconds for any single frame, that would explain it. In case you didn’t dig into all the details from the thread I linked above, there is nothing we can do to prevent your app from being killed if it takes >2sec to render a frame. The best we can do is the solution I provided in that thread where you dismiss the compositor layer (Metal rendering) while you preload shaders or do whatever it is that’s taking too long, and then bring it back up again. There’s just no other way around it. If you’re rendering to a CompositorLayer on visionOS, you can’t delay more than 2s or the app is killed.

One last thing to remember about the 2-second delay: the OS does not kill your app for this reason as long as the debugger is a attached. When you see the warning about “content may be head-locked during debugging”, it’s telling you “I would have killed the app if not for the debugger.” There’s no difference between hitting one of these long-running frames and when you hit a breakpoint for >2s in the debugger so they had to add a special rule to keep the app alive in this case even when it’s paused on a single frame.

This is probably doing more harm than good. We want your code running as fast as possible!

I wouldn’t expect this to have much of an impact. In practice you’ll need to be able to run debug/release builds anyway, so if any of this caused/fixed the issue it would still be an issue.

Certainly! :slight_smile: If you build the Metal Sample you should see a reasonably complex scene which demonstrates all of the platform features with Metal rendering. It runs fine on visionOS 2 and comes with the latest 2.x plugins. I’d say that scene is the “gold standard” for a working baseline (I may be a little biased, as its creator :wink: )

Again, nothing is certain, and I have been known to be wrong in the past, but I’m pretty sure this isn’t the issue.

It’s possible that the app is compiling shaders when it gets killed and those get cached to disk. You might want to try the metalCompileShaderBinary setting as a quick fix. If the issue is the 2s deadline, and you’re hitting it for some other reason, you should check out the long load example I shared in that thread. It requires that you first figure out where you have a bottleneck and carve out the shutdown/restart code around it, but if it’s something like pre-warming shaders, there are some examples out there of apps (like Vacation Simulator) which have been able to work around this issue. Otherwise, maybe we’ll hear from other users with similar issues and be able to learn something from them.

Whew! :cold_sweat: That’s a wall of text if I ever saw one. Hopefully some of the threads I linked to shed some light on the issues you’re seeing, and it’s as simple as ticking the box for pre-compiled shaders. If not, I’ll let the broken record skip one last time and humbly ask for a bug report with your project attached. :pleading_face: Without that, I think this :brick: :capital_abcd: is the best I can do :upside_down_face:

Thanks for reaching out, and good luck!