Mac OS X Reference Library Apple Developer
Search

Troubleshooting Spotlight Importers

Rare is the project that is flawless from the start. Troubleshooting a Spotlight importer can be difficult given that it is run by the system automatically as required and is run outside the development environment.

This article describes how to explicitly run your metadata importer for testing and provides a number of techniques for troubleshooting problems.

Where should I install my Spotlight importer?

Your Spotlight importer typically resides within your application’s bundle in the subdirectory MyApp.app/Contents/Library/Spotlight. Importers can also be installed in one of the following locations:

~/Library/Spotlight
/Library/Spotlight

If your importer is not part of an application bundle, you should create an installer package that installs the importer in one of the above locations. In order to have existing files imported, you will need to have a postinstall script for your installer that includes the following command, specifying your importer install location:

/usr/bin/mdimport -r InstallDirectory/YourPlug-In

When will the Spotlight importer in my application bundle re-index files?

When a user first runs your application, the Spotlight importer is found and Spotlight will begin importing any existing documents. If you update your application and the Spotlight importer, you should ensure that the importer bundle has a different date stamp. When the updated application is run for the first time Spotlight will re-index the existing files with the new importer.

Note: This behavior was added in the Mac OS X 10.4.1.

How can I determine if my Spotlight importer is being found?

Running the mdimport command (located in /usr/bin) with the -L option returns a list of all the currently recognized importers and their paths.

/usr/bin/mdimport -L
2005-01-16 02:56:37.634 mdimport[673] Paths: id(501) (
    "/System/Library/Spotlight/RichText.mdimporter",
    "/System/Library/Spotlight/Image.mdimporter",
    "/System/Library/Spotlight/Audio.mdimporter",
    "/System/Library/Spotlight/Font.mdimporter",
    "/System/Library/Spotlight/PDF.mdimporter",
    "/System/Library/Spotlight/Chat.mdimporter",
    "/System/Library/Spotlight/iCal.mdimporter",
    "/System/Library/Spotlight/Mail.mdimporter",
    "/System/Library/Spotlight/QuickTime.mdimporter",
    "/System/Library/Spotlight/vCard.mdimporter",
    "/Users/me/Library/Spotlight/MyCustomImporter.mdimporter",
    "/System/Library/Spotlight/QuartzComposer.mdimporter",
    "/System/Library/Spotlight/PS.mdimporter",
    "/System/Library/Spotlight/SystemPrefs.mdimporter",
    "/System/Library/Spotlight/Application.mdimporter"
)

Why isn’t my bundled importer being found?

If your importer resides within your application’s wrapper, it may not be found automatically during testing. Importers are detected when the bundle’s modification date is changed. You can explicitly register your application by specifying the -f flag to lsregister. The lsregister tool is found in /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Versions/A/Support/ on Mac OS X v10.5 and later.

lsregister -f MyApp.app

Another possibility is that your application may be untrusted. Spotlight importers are not loaded from untrusted applications. Launching the application for the first time causes the application to be trusted.

I've updated my importer and copied it to a Spotlight directory, but the old importer is still being used

New Spotlight importers are detected by comparing the date of the top-level .mdimporter directory. If the date is the same as a previously loaded importer, the new importer is not detected. If you copy the updated importer to the Spotlight directory using cp -r the change is not noted by Spotlight. The solution is to either remove the existing importer before copying the updated version, or use the touch command on the importer's .mdimporter directory to explicitly update the date.

How do I test my importer?

You can test your Spotlight importer using the mdimport command (located in /usr/bin). Run mdimport with the debug level set to 2 and specify a file that you can import data from:

/usr/bin/mdimport -d2 test.myCustomDocument

This command produces out like this:

2005-01-16 02:59:04.930 mdimport[678] Import '/Users/me/Documents/test.myCustomDocument'
type 'com.apple.mycocoadocumentapp.mycustomdocument'
using 'file://localhost/Users/me/Library/Spotlight/MyCustomImporter.mdimporter/'
2005-01-16 02:59:04.931 mdimport[678] Sending attributes
of '/Users/me/Documents/test.myCustomDocument' to server.
Attributes: '{
    "_kMDItemImporterCrashed" = <null>;
    "com_apple_metadata_modtime" = 127555123.1940155;
    "com_apple_myCocoaDocumentApp_myCustomDocument_notes" = "Remember to feed the cats!";
    kMDItemAuthors = ("Tori”,”Simon",”Daniel”);
    kMDItemContentType = "com.apple.mycocoadocumentapp.mycustomdocument";
    kMDItemContentTypeTree = ("com.apple.mycocoadocumentapp.mycustomdocument", "public.data", "public.item");
    kMDItemDisplayName = {"" = "test.myCustomDocument"; };
    kMDItemKind = {en = DocumentType; };
    kMDItemTitle = "Be sure to remember to...";
}'

The first line of the output indicates the file that is being imported, as well as the UTI that the file maps to. The remaining lines list the attribute keys and values that were imported from the file.

You should ensure that all the appropriate metadata keys that your importer returns are present in the output. You'll notice that a number of metadata keys specific to the file system are also available for each file. These are provided by the metadata system and are not your responsibility.

How do I debug my importer using gdb?

You can debug your importer by running mdimport under gdb.

The following command will load mdimport under gdb:

gdb mdimport

Once mdimport has started set a breakpoint on your import function:

b MyImporterGetAttributesFromFileFunction

Then start the mdimport process, specifying the file to import:

r /path/to/my/test/file

What does the system think the UTI is for a document?

You can determine the UTI that the system thinks belongs to your file by using the mdimport command with a debug level of 1:

/usr/bin/mdimport -d1 test.myCustomDocument

The output shows the UTI type that the system has determined for the file:

 2005-01-16 03:00:07.212 mdimport[683] Import '/Users/me/Documents/ test.myCustomDocument'
 type 'com.apple.mycocoadocumentapp.mycustomdocument'  using
'file://localhost/Users/me/Library/Spotlight/MyCustomImporter.mdimporter/'

The type should match the UTI that your importer supports.

Running mdimport returns nothing

If running mdimport with a debug level of 1 returns no output, you should ensure that the file you're attempting to import is not in the /tmp directory or some other System directory. Files in those locations are not imported.

Running mdimport returns an unexpected UTI

If running mdimport returns a UTI other than one you expect, you'll need to ensure that the file you're attempting to import is actually the type of file you think it is. The UTI of a file is determined by the extension or file type.

It is also possible that a dynamic UTI is returned:

2005-01-16 03:01:16.989 mdimport[691] Import '/Users/me/Documents/test.myCustomDocument'
 type 'dyn.ah62d4rv4ge8048pdsz31k55rqv10g7prqz1hkqu' no mdimporter

Typically, the return of a dynamic UTI indicates that the file is not mapping to a known UTI. You should check that:

  1. The test file is the correct file type.

  2. The test file has the correct filename extension or file type set.

  3. If your application is declaring the UTI type for the document, that the application's Info.plist file has the correct entries in the UTExportedTypeDeclarations entry as shown here:

        <key>UTExportedTypeDeclarations</key>
        <array>
            <dict>
                <key>UTTypeConformsTo</key>
                <array>
                    <string>public.data</string>
                </array>
                <key>UTTypeDescription</key>
                <string>My Document Type</string>
                <key>UTTypeIdentifier</key>
                <string>com.apple.mycocoadocumentapp.mycustomdocument</string>
                <key>UTTypeTagSpecification</key>
                <dict>
                    <key>public.filename-extension</key>
                    <array>
                        <string>myCustomDocument</string>
                    </array>
                <key>com.apple.ostype</key>
                <string>T78q</string>
                </dict>
            </dict>
        </array>
  4. Ensure that your application lives in a location where Launch Services can detect the mappings. Running the application also ensures that the mappings are made.

mdimport does not return my metadata attributes

If running mdimport with a debug level of 3 does not list any of your custom metadata attributes, you should check that:

  1. Your metadata importer is being found using the mdimport -L command.

  2. Your metadata importer's Info.plist file has the correct plug-in type for metadata importers in the CFPlugInTypes entry. The key should be 8B08C4BF-415B-11D8-B3F9-0003936726FC:

        <key>CFPlugInTypes</key>
        <dict>
            <key>8B08C4BF-415B-11D8-B3F9-0003936726FC</key>
            <array>
                <string>8AED83B3-C412-11D8-85A3-000393D59866</string>
            </array>
        </dict>
  3. The UUID that you created for your importer is unique and is in both the CFPlugInFactories and CFPluginTypes entries of the importer's Info.plist file. Here, the UUID is 8AED83B3-C412-11D8-85A3-000393D59866:

        <key>CFPlugInFactories</key>
        <dict>
            <key>8AED83B3-C412-11D8-85A3-000393D59866</key>
            <string>MetadataImporterPluginFactory</string>
        </dict>
        <key>CFPlugInTypes</key>
        <dict>
            <key>8B08C4BF-415B-11D8-B3F9-0003936726FC</key>
            <array>
                <string>8AED83B3-C412-11D8-85A3-000393D59866</string>
            </array>
        </dict>
  4. You have the correct UTI type for your importer listed in the LSItemContentTypes entry in the importer's Info.plist file:

        <key>CFBundleDocumentTypes</key>
        <array>
            <dict>
                <key>CFBundleTypeRole</key>
                <string>MDImporter</string>
                <key>LSItemContentTypes</key>
                <array>
                    <string>com.apple.mycocoadocumentapp.mycustomdocument</string>
                </array>
            </dict>
        </array>
  5. Your UTI is all lowercase in the Info.plist and the schema.xml files.

  6. If your importer reads metadata from a document package ensure that the UTTypeConformsTo entry in the importer's Info.plist includes com.apple.package as a UTI.

  7. Your schema.xml file is valid.

    You can test whether your schema.xml file is well formed by running the command mdcheckschema (located in /usr/bin).

    /usr/bin/mdcheckschema ~/Library/Spotlight/MyCustomImporter.mdimporter/Contents/Resources/schema.xml
    /Users/me/Library/Spotlight/MyCustomImporter.mdimporter/Contents/Resources/schema.xml : succesfully parsed.
  8. Your implementation of GetMetadataForFile is populating the dictionary with the correct metadata entries and is returning true.

  9. You return only CFTypes of CFString, CFNumber, CFBoolean, and CFDate as attribute values. If an attribute is specified as multivalued, you must return a CFArray of the expected CFType.

What are the imported metadata attributes for a specific file?

You can determine the metadata attributes and values in the system store for a file by using the mdls command:

mdls /Applications/iTunes.app
/Applications/iTunes.app -------------
kMDItemAttributeChangeDate = 2005-01-16 03:03:14 -0500
kMDItemContentType         = "com.apple.application-bundle"
kMDItemContentTypeTree     = (
    "com.apple.application-bundle",
    "com.apple.application",
    "public.executable",
    "com.apple.bundle",
    "public.directory",
    "public.item",
    "com.apple.package"
)
kMDItemCopyright           = "iTunes 4.7, Copyright 2000-2004 Apple Computer, Inc."
kMDItemDisplayName         = "iTunes"
kMDItemFSContentChangeDate = 2005-01-08 18:17:52 -0500
kMDItemFSCreationDate      = 2005-01-08 18:17:52 -0500
kMDItemFSCreatorCode       = 0
kMDItemFSFinderFlags       = 0
kMDItemFSInvisible         = 0
kMDItemFSLabel             = 0
kMDItemFSName              = "iTunes.app"
kMDItemFSNodeCount         = 1
kMDItemFSOwnerGroupID      = 80
kMDItemFSOwnerUserID       = 0
kMDItemFSSize              = 0
kMDItemFSTypeCode          = 0
kMDItemID                  = 64286
kMDItemKind                = "Application"
kMDItemLastUsedDate        = 2005-01-16 01:01:10 -0500
kMDItemUsedDates           = (
    2005-01-08 18:17:52 -0500,
    2005-01-13 19:00:00 -0500,
    2005-01-15 19:00:00 -0500
)
kMDItemVersion             = "4.7"

You can also specify a specific metadata attribute to return the value of:

mdls -name kMDItemContentType /Applications/iTunes.app
/Applications/iTunes.app -------------
kMDItemContentType = "com.apple.application-bundle"

Why isn’t Spotlight finding my document bundles when they are saved by my application?

If your application saves its documents as a bundle, you must take precautions to ensure that Spotlight doesn’t attempt to import your document before all the data is written to the bundle.

See “Spotlight and Document Bundles” for additional details.




Last updated: 2009-10-11

Did this document help you? Yes It's good, but... Not helpful...