Verify macOS file associations through double-click testing

DevOps & CI/CD ·~4 min read

Verify macOS file associations through double-click testing

When debugging a macOS document app remotely, developers often run into a puzzling result: a sample file opens when they explicitly specify the app in Terminal, but double-clicking that same file on the desktop opens another app or prompts them to choose one. The first success only shows that the app can be asked to handle the file; it does not verify the file association. To find the cause, treat type declaration, file handling, and default opening as three separate outcomes.

This guide uses a custom .notejson file as an example. Its contents are JSON, while its extension identifies it as the app’s own document format. Run these checks against a built, runnable macOS app. Use only fictitious data in the test file, not a production document.

Declare the file type before checking the extension

A custom format needs a stable type identifier. In this example, the identifier is dev.sample.notejson, the extension is notejson, and the contents conform to JSON. The app’s configuration must do two things: export the type and declare that the app can open it. Checking a filename suffix in code alone will not create a Finder association.

After configuring the exported type and Document Types in the Xcode app target, inspect the Info.plist in the built app bundle. The exported type should specify its identifier, extension, and conforming parent type; the document type should reference that same identifier. If the example app can only display files, set its document role to Viewer rather than claiming editing support that has not been implemented.

Inspect the built app bundle, not settings in the project interface that may not have made it into the build.

If the format is not actually JSON, do not declare that it conforms to JSON just to make the example work. Type relationships must reflect the real contents. Rebuild the app after changing a declaration; an existing app bundle will not update itself when project settings change.

Inspect the declarations in the delivered app bundle

First, put the app being checked at a fixed path. The commands below use /Applications/NoteReader.app as an example. Change APP to your app’s path before running them:

APP="/Applications/NoteReader.app"
test -d "$APP/Contents" || exit 1
plutil -extract UTExportedTypeDeclarations json -o - "$APP/Contents/Info.plist"
plutil -extract CFBundleDocumentTypes json -o - "$APP/Contents/Info.plist"

Check the first output for dev.sample.notejson and notejson, and the second for the same type identifier and the document role. If plutil reports that a key is missing, return to the target configuration and build output before testing a double-click. Some projects generate the final property list from build settings, making the file inside the bundle the authoritative source.

On a remote Mac, also confirm that you are checking the copy you just built. If an app with the same name remains in both Downloads and Applications, a Terminal test that specifies a path and a Finder default-opening test may use different copies. Record the bundle path and remove old copies that are not part of this test before repeatedly changing type declarations.

Use two opening methods to isolate the failure

Create a temporary sample. First open it with the app explicitly specified, then test the system’s default choice:

APP="/Applications/NoteReader.app"
CASE="$(mktemp -d)"
printf '{"title":"association-check"}\n' > "$CASE/demo.notejson"

open -a "$APP" "$CASE/demo.notejson"
open "$CASE/demo.notejson"

A successful open -a means the specified app was asked to handle the file. You still need to check that the app actually displays the sample contents; seeing a window appear does not prove that reading succeeded. The second command leaves the app unspecified, so it tests the default-opening choice. You can also double-click the same sample in Finder and note which app opens.

The default association depends on the apps installed on that Mac and the user’s choices. Record “result when the app was specified” and “result of default opening for the current user” separately. Do not treat the latter as a result that will necessarily be the same on every machine. If the system prompts you to choose an app, record that too; it is not a successful automatic association.

Diagnose the symptom before changing file-reading code

What you observe Check first
The app bundle lacks a type or document declaration Target configuration and the actual build output
The specified app cannot read the file either File contents and the app’s file-handling and parsing logic
The specified app can read it, but default opening goes elsewhere The current user’s default association and other copies of the app
The app launches but shows a blank document Error handling after receiving the file and the UI state

The last two cases are particularly easy to confuse. Even after the system passes a file to the app, the app may reject it because the sample is malformed. Conversely, an app may parse the file perfectly while the system still does not select it by default. Identify where the routing or handling fails before changing the corresponding code.

After checking, delete the temporary sample. Keep the app bundle path, type identifier, sample extension, and results of both opening methods in the build record. Reuse these checks the next time you change Info.plist or the document-reading code. That way, you can tell whether a change affected the file association or the app itself instead of relying on “I double-clicked it once” as your conclusion.

Frequently asked questions

Why does double-click open another app when open -a succeeds?

The -a option selects an app explicitly and bypasses the default-app decision. Inspect the bundle’s document type declaration, then test opening the file without -a or by double-clicking it.

What should I check if the app receives the file but cannot read it?

File routing and content parsing are separate steps. Verify that the file contains the declared format, then inspect the app’s reader and its error output.

Bring a cloud Mac into your workflow

VPSPush offers remotely accessible, dedicated physical Macs. Choose a location and rental term, then review the access details and final price in your order.

Explore cloud Mac plans and order