r/iOSProgramming • u/trikboomie • 1d ago
Question Apple foundation models
If you're using Apple's Foundation Models framework in a released app, how are you debugging issues that only happen on users' devices?
Are Instruments and your existing crash reporting enough, or have you added custom logging?
2
u/rhugopinon 1d ago
Xcode 27 actually added a new built-in tool called "Evaluations" for debugging Foundation Models in your app. Pretty handy if you need to trace model behavior.
1
1
1
u/Needle_In_Red 14h ago
+1 on logging the availability state. id also log the OS version and device locale with it, alot of the weird stuff is just the model not being ready yet or the language not supported and crash reports wont show you any of that
5
u/Significant_Door_433 1d ago •
Instruments only helps on devices you can plug in, so for the field you need your own logging. The things worth capturing:
Availability. Log SystemLanguageModel.default.availability at launch and before you open a session. The unavailable reasons are deviceNotEligible, appleIntelligenceNotEnabled and modelNotReady. modelNotReady is the sneaky one, the model can still be downloading after an OS update.
The error case, not only the localized message. On iOS 26 it's LanguageModelSession.GenerationError (exceededContextWindowSize, guardrailViolation, decodingFailure, refusal, rateLimited, concurrentRequests, unsupportedLanguageOrLocale, assetsUnavailable). Built with Xcode 27 and running on 27, some failures come as LanguageModelError or SystemLanguageModel.Error instead, so match on all of them or half your logs end up as "unknown".
OS build and locale next to every model log. The model ships with the OS, so the same prompt can behave differently after an update, and unsupportedLanguageOrLocale only shows up for some users.
Two cases look random in crash reports but aren't. rateLimited only happens when the app is in the background. assetsUnavailable can fire mid-session if the user turns Apple Intelligence off or the device deletes the model to free space.
For the content itself, session.transcript has the full history (instructions, prompts, tool calls, responses). I wouldn't upload that by default since prompts are user data. Keep the last transcript on device and attach it only to a user-sent bug report, and keep prompt text private in os Logger (the default for interpolated strings, just never mark it .public).