iOS 18.4 - HomeKit actions from AppIntent fail when triggered from Widget

Hi all,

Since updating to iOS 18.4, I'm experiencing a regression with AppIntents triggered from Widgets.

In my app, I use AppIntents inside a WidgetKit extension to control HomeKit devices. This setup was working perfectly up to iOS 18.3. However, starting with iOS 18.4, when the AppIntent is triggered from the widget and the main app is not running, the action fails with this error:

Error Domain=HMErrorDomain Code=80 "Missing entitlement for API." UserInfo={ NSLocalizedFailureReason=Handler does not support background access, NSLocalizedDescription=Missing entitlement for API. }

Interestingly, the exact same AppIntent works fine if the app is still alive in the background — it seems like the failure only occurs when the intent is handled by the widget process.

This looks like a behavior change or new restriction introduced in iOS 18.4. Has anyone experienced the same? Is there a new entitlement needed, or a recommended workaround?

Thanks in advance!

We need to look into this as a bug report with some system logs that we can analyze. Can you open a bug report in Feedback Assistant and attach a sysdiagnose to that report? Once you've done that, please post the FB number here so I can locate your report.

If you have any questions about filing a bug report, take a look at Bug Reporting: How and Why?

— Ed Ford,  DTS Engineer

Accepted Answer

I’ve finally resolved this issue after many hours of debugging — posting the full solution here in case it helps others.

✅ Problem

Since iOS 18.4, calling HomeKit APIs (like toggling accessories) from an AppIntent triggered by a Widget fails with the following error:

Error Domain=HMErrorDomain Code=80 "Missing entitlement for API." UserInfo={ NSLocalizedFailureReason=Handler does not support background access, NSLocalizedDescription=Missing entitlement for API. } This happens only when the intent runs inside the widget process, not when it runs in the main app (even in background).

✅ Solution Part 1: Force AppIntent to run in main app process

To bypass the limitations of the widget process, I made my AppIntent run in the main app instead, using the ForegroundContinuableIntent protocol.

You can do this by adding the following extension:

@available(iOSApplicationExtension, unavailable)
extension MyActionIntent: ForegroundContinuableIntent {}

Then declare your AppIntent as usual:

struct MyActionIntent: AppIntent {
init() {}
static var openAppWhenRun: Bool {
return false // Keep this false to avoid full app UI presentation
}
func perform() async throws -> some IntentResult {
// Call HomeKit APIs here
return .result()
}
}

With this, even when triggered from a widget, the intent runs in the app's process — which has proper entitlements and access to HomeKit.

🧨 BUT... another hidden problem was causing crashes After applying the above fix, the intent still didn't seem to work — or worse, the app was crashing silently when launched in background.

After deeper investigation, I found the real cause: I had a SwiftUI .backgroundTask(.appRefresh("MyBGTaskID")) { ... } modifier declared on the WindowGroup.

Apparently, when the app is launched in background by an AppIntent, this SwiftUI modifier behaves incorrectly — the background task is not properly registered, and causes a crash when triggered.

But this crash is invisible if you test by launching the app manually — because in that case, everything works fine, and the .backgroundTask behaves normally.

✅ Solution Part 2: Register background task manually

I fixed this issue by removing the SwiftUI .backgroundTask modifier and manually registering the background task the "classic" way, in the init() of the @main app struct:

import BackgroundTasks
@main
struct MyApp: App {
init() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "MyBGTaskID", using: nil) { task in
// Handle your task here
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

✅ Summary

iOS 18.4 introduced stricter sandboxing for AppIntents running inside Widgets. Use ForegroundContinuableIntent to force your AppIntent to run in the main app context (where HomeKit works). Beware of SwiftUI .backgroundTask modifiers — they may cause background crashes when the app is launched by an AppIntent. Use manual registration via BGTaskScheduler.shared.register(...) instead. Let me know if anyone else experienced the same issue, or if you found a better way to debug background crashes in SwiftUI contexts.

Hope this helps! 🙌

iOS 18.4 - HomeKit actions from AppIntent fail when triggered from Widget
 
 
Q