Missing types of files: the bug in UTIs

Almost exactly a year ago, I wrote one of my unrecognised gems here, about file types and UTIs. In case you’re confused about them, for Apple a UTI is a Uniform Type Identifier, not a urinary tract infection.

I followed that up with a utility to explore these unsung heroes of macOS and iOS, UTIutility, available from Downloads above, and was recently surprised when I discovered (thanks to my grandson) that there’s now a free iOS app called UTI Inspector, although I can’t understand how that could be useful on an iPhone.

In a nutshell, a Uniform Type Identifier, or UTI, is a formal designator of type which extends across files, folders, and more. Instead of the various systems in use for designating a JPEG image file, such as its extensions of .jpg or .jpeg, and MIME type of image/jpeg, Apple’s operating systems use a hierarchical system of type designators, in that case public.jpeg.

It’s essential for Mac and iOS developers to understand and use them, as they are the means by which an app declares which types of document it can handle, for example. Advanced users and system administrators are also likely to come across them from time to time.

The UTI system is designed so that every object – files and folders – in a file system has a UTI designator. Except it doesn’t quite work that way. Thanks to a very old bug, some ‘files’ in macOS don’t have a discoverable UTI at all. When an app is looking for specific types of file, if it uses the UTI to identify type, sooner or later it’s likely to stumble across items which don’t have a type. And that can cause a problem which the user may notice. Indeed, it can even cause apps to crash.

There are several ways that an app can request the UTI of a file or folder. Two popular methods which I use in apps are
try NSURL.getResourceValue(&theUTI, forKey: URLResourceKey.typeIdentifierKey)
or
let theUTI = try URL.resourceValues(forKeys: [URLResourceKey.typeIdentifierKey])
Both return the UTI in theUTI.

You’ll notice that both calls are made using the Swift code to try them. If the call returns an error, those two apps then have to handle that error, or the app may crash. Running those apps on certain folders, notably ~/Library, regularly returns errors which are accompanied by log entries which look like
2019-01-19 21:08:36.560996+0000 Alifix[66486:23689766] [default] *** Expected to get UTI for file '/Users/hoakley/Library/Application Support/Adobe/Acrobat/2015/Acrobat/Synchronizer/Notification' but got NULL on line (/LSCore.mm:2226). Flags are 0000000000003000. Please amend <rdar://problem/18605177> with this information.

Instead of those items returning a UTI, they’re returning a NULL, which is very bad news. This is an old bug judging by the Bug Reporter number given of 18605177, and may date back to the introduction of UTIs in macOS 10.5 – yes, that was in 2007. This is despite the fact that the item causing this problem is relatively modern, a part of Adobe Acrobat 2015. The item in question is reported as being a socket, and that gives the clue: UTIs don’t work with sockets and similar pseudo-files. Perhaps it’s just coincidence, but Adobe Acrobat has become exceedingly fragile here of late.

This bug can also result in odd error messages. In UTIutility, for example, I ask macOS for its description of the problem, and it reports that the file couldn’t be found, rather than its UTI couldn’t be obtained. Alifix just passes over such errors in silence, as it’s looking for Aliases, not Apple’s unfixed bugs.

I have seen several users with problems from crashing apps and the like who have reported this bug’s characteristic entries in the log. If you happen to come across it, you now know the cause. If it does crash or otherwise injure an app which you’re trying to run, you can point its developers at this article.

So UTIs can sometimes matter after all.