Confused by appintentsmetadataprocessor errors in Xcode 16?

Development / iOS

I’m currently building a new app for framing screenshots and adding backgrounds for social sharing called Shareshot that is in public Beta. It supplies a bunch of App Intents for Shortcuts integration so that you can batch-frame screenshots.

I tried building it with Xcode 16 betas and found a bunch of confusing build errors for code that builds fine in Xcode 15. You might bump into them too:

2024-07-18 21:33:51.168 appintentsmetadataprocessor[48853:35754477] Starting appintentsmetadataprocessor export
2024-07-18 21:33:51.204 appintentsmetadataprocessor[48853:35754477] error: At least one halting error produced during export. No AppIntents metadata have been exported and this target is not usable with AppIntents until errors are resolved.
error: Found multiple, identical identifiers for query: Query, each identifier must be unique

I was confused by this message. It uses “query” multiple times — I got a lot of them — and initially I just thought this was some straight-up new bug in appintentsmetadataprocessor which is part of the toolchain that processes your App Intents Swift source to extract static elements at build time, to build a JSON file containing metadata about your intents and bundles it into your app.

Eventually I worked out that the capitalised Query was the name of the nested query types used by several AppEntity types in my code:


public struct BackgroundOption: AppEntity, Equatable {    
    public var id: String { value.id }
    public let value: BackgroundInfo
    
    ...
    
    public static var defaultQuery = Query()
    
    public struct Query: EntityQuery {
       ...
    }    
}

I was advised that as of Xcode 16 the type name used for the query type in AppEntity(s) must be “globally” unique and the tooling does not use the fully qualified name of the type if it is nested, contrary to standard Swift scoping. This does seem to work fine in Xcode 15 so it is unclear why this has regressed.

The error was occurring for me as I have several AppEntity that use this same pattern, all using the same locally-scoped Query name — if I had only one it wouldn’t have happened. The workaround is to uniquely name all these nested types, e.g:


public struct BackgroundOption: AppEntity, Equatable {    
    public var id: String { value.id }
    public let value: BackgroundInfo
    
    ...
    
    public static var defaultQuery = BackgroundOptionQuery()
    
    public struct BackgroundOptionQuery: EntityQuery {
       ...
    }  
}

It’s annoying but it’s not a huge problem, if a little confusing at first. It does make me wonder that if I have another global type BackgroundOptionQuery I’ll get other weird build failures if it doesn’t also conform to EntityQuery.

I raised a feedback about this, and received the response that this “Works as currently designed”. So it looks like we need to change our code for Xcode 18. (FB14375756 “appintentsmetadataprocessor fails to process AppEntity with nested query types”).

Hopefully this saves somebody some time.

The Author

Marc Palmer (Twitter, Mastodon) is a consultant and software engineer specialising in Apple platforms. He currently works on the iOS team of Concepts sketching app, as well as his own apps like screenshot framing and backgrounds app Shareshot and video subtitling app Captionista. He created the Flint open source framework. He can also do a pretty good job of designing app products. You can find out more here.