I have a habit tracker app that uses App Intents and Shortcuts. The app uses SwiftData to persist data, just in case that's important.
One of the shortcuts serves to log habits. However, when the app has been in the background for a good while (over an hour or so), that particular shortcut always fails when I try to run it in the Shortcuts app with the system error "Invalid action metadata" caused by "a bug in the host app".
The app has a total of 9 shortcuts, and it's just this one particular shortcut that seems to be failing – the others continue to run without any issues even after the app has been in the background for a long time.
The app intent/shortcut that is problematic is the one called HabitEntryAppIntent
. For example purposes, I've also included one of the non-problematic intents in the code snippet below called HabitEntryCounterForTodayAppIntent
. Both of these intents have one @Parameter
value of type HabitEntity
.
I'll post code snippets in the replies because the character limit is not large enough to include them here, or view them in this GitHub gist:
I've tried everything I can think of whilst debugging, but none of the following fixed the error:
- Removed all usage of
@MainActor
andmainContext
by replacing theModelContext
used inperform()
with a locally created property. - Removed all usage of static shared properties like
Calendar.shared
andModelContainer.shared
and replaced them with local properties. - Removed all non-essential code such as the code for
context.undoManager
andWidgetManager.shared.reload(.all)
and really striped it all down to the absolute essentials. - Reduced the number of shortcut phrases in the problematic shortcut because there was perhaps too many (>10) originally.
You might have noticed that the perform()
method in the problematic intent manipulates the database whilst the non-problematic intent only reads the database. Given that the two intents in the snippet above both have the same @Property(...) var habitEntity: HabitEntity
values, I tried to swap the contents of the perform()
methods over to see what would happen.
And here's what's strange: When the perform()
method from the problematic HabitEntryAppIntent
is used in HabitEntryCounterForTodayAppIntent
, it works without any issues and successfully logs habits! And then when the perform()
method from the non-problematic HabitEntryCounterForTodayAppIntent
is used in HabitEntryAppIntent
it fails with the system error "Invalid action metadata". This suggests that the problem is not in the code that logs the habit entries but rather something is wrong with HabitEntryAppIntent
itself.
I also tried changing the metadata used in HabitEntryAppIntent
and its shortcut. I copied all the metadata used in HabitEntryCounterForTodayAppIntent
(the title
, description
, parameterSummary
etc) and pasted it into HabitEntryAppIntent
. And did the same with the metadata in the shortcut (phrases
, shortTitle
etc) so that all the metadata used in HabitEntryAppIntent
matched that used in HabitEntryCounterForTodayAppIntent
. However, the shortcut for HabitEntryAppIntent
continued to fail.
Thus, it doesn't seem to be an issue with the code in perform()
because that code succeeds when used in another app intent. And, despite the "metadata" error message, it doesn't seem to be an issue with the metadata in the app intent because I've tried using metadata from the non-problematic intent but it still fails.
I have watched all WWDC videos related to app intents and shortcuts, and looked through the developer forum for similar questions, but I'm completely stumped by this issue and why it's only affecting one of my shortcuts.
Also worth mentioning is that the widgets in the app that log habits using the same app intent do not suffer the same issue; they continue to work even after the Shortcut has failed.
Moreover, if I try running the problematic shortcut for HabitEntryAppIntent
and see the system error message, then run the shortcut for HabitEntryCounterForTodayAppIntent
(which always succeeds), and then try running the HabitEntryAppIntent
shortcut again, it then runs successfully on the second attempt. It seems that running HabitEntryCounterForTodayAppIntent
fixes the issue, at least temporarily.