Notarytool Notarization Failure: A 2026 Debugging Checklist

Apple stopped accepting notarization uploads from altool and Xcode 13 or earlier on November 1, 2023. That date is the first diagnostic checkpoint for any old release script. If you see a notarytool notarization failure, do not upload the same file again blindly. Save the submission ID, read the notary log, and identify whether the failure is in signing, notarization scanning, ticket stapling, or Gatekeeper validation. (Apple’s notarization workflow)

This guide is for you if you distribute a macOS app through a website, DMG, PKG, or ZIP file. It also targets small teams whose scripts sometimes return Invalid, remain in In Progress, or pass notarization but fail during stapler or customer-side launch checks.

01 Start With The Submission State

Notarization, code signing, ticket stapling, and Gatekeeper are separate checks. A signed app can fail notarization. An accepted submission can still have a stapling problem. A stapled app can still expose a runtime or packaging defect that you have not tested.

Treat the terminal output as a routing signal, not the final diagnosis.

Use placeholders for all account and package values:

xcrun notarytool submit "/path/to/ARCHIVE.zip" \
  --keychain-profile "KEYCHAIN_PROFILE" \
  --wait

Record these fields before changing anything:

  • Submission ID
  • Archive name
  • Returned status
  • Upload result
  • Processing result
  • The exact artifact submitted
  • The commit or build identifier used to create it

If the command returns Invalid, retrieve the JSON log:

xcrun notarytool log "SUBMISSION_ID" \
  --keychain-profile "KEYCHAIN_PROFILE" \
  "notary-log.json"

Apple’s documented log format includes the submission status, a summary, issue severity, message, and path. That path is often more useful than the short error shown in the terminal. It can point to a helper tool, framework, plug-in, XPC service, or nested executable rather than the outer .app bundle. (Apple’s notarization log guidance)

Use this first branch:

  • If upload fails before a submission ID exists, investigate credentials, network access, archive readability, or the selected developer tools.
  • If the submission is still processing, keep the ID and query the status instead of creating duplicate submissions.
  • If the status is Invalid, download the log before rebuilding.
  • If the status is Accepted, move to ticket stapling and local policy validation.
  • If stapling fails, do not assume the code signature was rejected.
  • If spctl or a customer launch fails after acceptance, investigate the final artifact, quarantine state, architecture, permissions, and runtime behavior separately.

Apple describes notarization as an automated scan and not as App Review. A successful result means the submitted software passed that notary workflow. It does not prove that every supported macOS release, hardware architecture, user permission path, or third-party plug-in will behave correctly.

02 Developer ID And Signature Chain

A macOS app distributed outside the Mac App Store needs the correct Developer ID signing identity. The identity must match the object being signed:

  • Use a Developer ID Application certificate for the app and executable code.
  • Use a Developer ID Installer certificate for a flat installer package.
  • Do not substitute a Mac App Distribution, development, ad hoc, or self-signed identity for a direct-distribution package.
  • Confirm that the private key is present in the keychain used by the build account.
  • Confirm that the certificate and private key form one usable signing identity.

Apple states that an app signed with the wrong certificate can produce a log message indicating that the binary is not signed with a valid Developer ID certificate. The same documentation distinguishes the application certificate from the installer certificate. (Apple’s common notarization issues)

Check the outer app:

codesign --verify --deep --strict --verbose=4 \
  "/path/to/APP.app"

codesign -dvvv \
  "/path/to/APP.app"

Then inspect the signing identity and timestamp in the verbose output. Do not stop after the outer bundle passes. --deep is useful as a diagnostic signal, but it should not replace an explicit signing order for nested code.

Check the important failure patterns:

  • Private key missing: the certificate may appear in Keychain Access, but signing or export fails because the corresponding private key is unavailable to the build account.
  • Wrong certificate type: the app may be signed successfully, yet the notary log rejects the identity because it is not a valid Developer ID identity.
  • Missing secure timestamp: a custom signing command may omit the timestamp that standard distribution workflows add automatically.
  • Signature changed after signing: modifying a binary, resource, framework, or embedded helper after signing invalidates the seal.
  • Broken chain or inaccessible keychain: the signing identity exists on one Mac but not in the keychain or search list used by the remote build process.

Apple’s certificate documentation explains how to create Developer ID certificates and use them for software distributed outside the Mac App Store. Check the certificate state in your Apple Developer account and the actual signature output. Do not infer certificate validity from one failed build. (Apple’s Developer ID certificate documentation)

03 Hardened Runtime And Entitlements

Hardened Runtime is not a cosmetic switch. Apple requires it for macOS apps submitted for notarization. Enabling it is the baseline; the next question is whether your entitlements accurately describe what the app does.

Inspect the signed entitlements:

codesign -d --entitlements :- \
  "/path/to/APP.app"

Review three different classes of problems.

Incorrect Entitlement Format

Embedded entitlements must be properly formatted. A malformed entitlement can cause code-signature validation errors before application behavior testing. Do not assume that a valid property-list file is automatically a valid release entitlement set. Inspect the entitlements embedded in the signed binary, not only the source file used by Xcode.

Unnecessary Exceptions

Runtime exceptions should exist only when the application needs them. Common examples include JIT execution, unsigned executable memory, library validation exceptions, and dynamic linker environment variables. If your app does not need one, remove it from the release signing configuration.

Apple’s Hardened Runtime documentation recommends using only the entitlements required by the app’s functionality. It also explains that some entitlements weaken specific runtime protections. (Apple’s Hardened Runtime documentation)

Content Changed After Signing

A frequent pattern is:

  1. Build the app.
  2. Sign the nested helper.
  3. Sign the outer app.
  4. Copy a framework, patch a configuration file, or run a packaging script.
  5. Submit the modified result.

The final object is no longer the object that was signed. Make signing the last content-changing stage. After signing, run verification again and package only the verified output.

Pay special attention to com.apple.security.get-task-allow. A release binary should not carry development-only debugging permissions unless the application has a documented production requirement. A development export can therefore pass local testing while the release archive fails notarization.

Release rule: If an entitlement exists because a debugger, plug-in loader, or local development tool needs it, prove that the production binary still needs it before retaining it.

04 Nested Code And Artifact Structure

The outer app signature is not a complete release certificate. A macOS bundle can contain several independently signed objects:

  • Frameworks
  • Plug-ins
  • XPC services
  • Login items
  • Command-line tools
  • Embedded helper applications
  • Third-party Mach-O binaries
  • System extensions or other special bundles

When the notary log includes a path, follow that path into the bundle. Do not fix only the top-level application if the issue names a nested object.

A useful evidence chain is:

codesign --verify --strict --verbose=4 \
  "/path/to/APP.app/Contents/Frameworks/FRAMEWORK.framework"

codesign --verify --strict --verbose=4 \
  "/path/to/APP.app/Contents/XPCServices/SERVICE.xpc"

spctl --assess --type execute --verbose=4 \
  "/path/to/APP.app"

Use actual paths only in your local shell. Keep TEAM_ID, BUNDLE_ID, certificate names, and customer data out of shared logs.

The signing order matters. Sign the deepest code first, then its containing bundle, and finish with the outer app. If you sign the outer app and later replace an embedded framework, the outer seal no longer matches the bundle contents.

The package type changes the final checks:

  • DMG: validate the app inside the disk image and the disk image itself when you distribute the DMG as the download artifact.
  • PKG: sign the package with the Developer ID Installer identity, while also ensuring the app inside is correctly signed.
  • ZIP: notarize the archive when appropriate, but do not try to staple a ticket directly to the ZIP. Staple the individual item inside the archive, then create a new ZIP for distribution.

The diagnostic layers are shared, but the final object is not. Always test the file a customer will download, not only the intermediate .app.

05 Authentication, Upload, And Stapling

A failure in authentication or network access is not a failed malware scan.

Keep these cases separate:

  • API key or keychain profile cannot authenticate.
  • The archive cannot reach the upload service.
  • The upload completes but processing remains unfinished.
  • The log cannot be retrieved.
  • The submission is accepted but the ticket cannot be stapled.
  • Gatekeeper cannot validate the final downloaded artifact.

For scripted environments, use a Keychain profile or another supported credential method. Keep the profile name as a placeholder in documentation:

xcrun notarytool store-credentials "KEYCHAIN_PROFILE" \
  --apple-id "APPLE_ID_PLACEHOLDER" \
  --team-id "TEAM_ID_PLACEHOLDER" \
  --password "APP_SPECIFIC_PASSWORD_PLACEHOLDER"

For production automation, review the current notarytool help output and Apple’s current authentication guidance before selecting a credential method. A command that works on your laptop may fail on a remote Mac because the keychain is locked, the login session is different, or the private key was never imported.

After an accepted result, staple the supported artifact:

xcrun stapler staple "/path/to/APP.app"

Then validate the stapled object:

xcrun stapler validate "/path/to/APP.app"

A successful submission and a successful stapling operation are different results. If the object is unsupported for direct stapling, change the artifact sequence rather than changing the signing identity.

For a remote Mac, store credentials under a dedicated build account. Restrict access to the private key. Do not place API keys, issuer identifiers, or keychain passwords in a repository, build artifact, terminal transcript, or public CI log.

06 Gatekeeper Verification

Gatekeeper is the customer-side policy check. It is not identical to the notary service.

After stapling, assess the exact distributable object:

spctl --assess --type execute --verbose=4 \
  "/path/to/APP.app"

For a disk image or installer, use the assessment mode appropriate to the object and confirm the result on a clean test account or clean test Mac. Remove old copies before testing when possible. A previous local approval can hide a packaging mistake.

Also test the download path:

  1. Upload the final DMG, PKG, or ZIP to the same type of distribution location customers use.
  2. Download it again.
  3. Confirm that the archive was not modified during upload or CDN handling.
  4. Extract or mount it.
  5. Run stapler validate where supported.
  6. Run spctl against the app or installer.
  7. Launch the application under a non-development user account.

A stapled ticket helps Gatekeeper validate software without depending on an online ticket lookup. It does not replace testing the real download path or the exact artifact that users receive.

07 Decision Branches For The Next Action

Use the following conditions instead of restarting the entire release process every time:

  • If no submission ID exists, choose credential, network, archive, or toolchain diagnostics. Do not debug entitlements yet.
  • If the log names a certificate or signature, return to the signing identity and nested-code checks. Do not change Hardened Runtime settings first.
  • If the log names Hardened Runtime or an entitlement, inspect the signed entitlements from the final archive. Do not inspect only the Xcode project file.
  • If the log names a nested path, verify that exact object and then resign from the inside out.
  • If the status is Accepted but stapling fails, validate the object type and final path. Do not automatically rebuild the app.
  • If stapling passes but Gatekeeper fails, test the downloaded artifact and quarantine path. Do not assume Apple rejected the submission.
  • If the same failure returns on every build, freeze the environment and compare the toolchain, keychain, signing identity, archive contents, and script inputs between runs.

08 Frequently Asked Questions

The following answers cover common search intents without collapsing different failure layers into one generic “notarization error.”

Notarytool Invalid Logs

The submission ID is the anchor for the investigation. Download the JSON log and inspect status, statusSummary, issues, severity, message, and path. If the path points to a nested binary, fix that object first. Preserve the original log before rerunning so you can compare whether the next submission removed the same issue.

Signed Apps That Still Fail

A signature check proves that a signature exists and can be verified under the command you used. It does not prove that the certificate is a valid Developer ID identity, that Hardened Runtime is enabled, that entitlements are suitable, or that every embedded object remains unchanged. Run verification against the final archive, not an earlier build directory.

Stapler Failures After Acceptance

An accepted submission has a ticket, but the ticket may not be attachable to every file type. ZIP is the important exception. Staple the app, DMG, or PKG that belongs inside the archive, validate it, and then rebuild the ZIP. If a supported object fails, preserve the exact stapler output and check whether the file was altered after acceptance.

Remote Credential Storage

A remote Mac should have a stable build account, a controlled keychain, and a credential profile that can be used without an interactive password prompt. Verify the workflow after logout, reboot, and keychain locking. If the script only works while your graphical login session is open, it is not yet a reliable release environment.

DMG, PKG, And ZIP Differences

The initial diagnosis is shared because all formats can contain signed code. The final validation is format-specific. PKG adds an installer-signing layer. DMG adds a disk-image distribution layer. ZIP requires a correctly stapled item inside the archive because the ZIP itself cannot receive the ticket directly.

09 Remote Mac Release Acceptance Card

The task-specific live acceptance block is omitted here because no CALMVPS test record, rental period, delivery method, credential persistence record, or redacted signing and Gatekeeper results were provided. Do not replace missing production evidence with invented hardware, price, region, or performance claims.

You can still run this acceptance sequence on the Mac that will own your release process:

  • [ ] Confirm the selected Xcode Command Line Tools with xcode-select.
  • [ ] Confirm xcrun notarytool help and xcrun stapler help run under the build account.
  • [ ] Import the Developer ID Application identity and verify the private key.
  • [ ] Import the Developer ID Installer identity if PKG distribution is used.
  • [ ] Create or restore the approved Keychain profile.
  • [ ] Build a clean release archive.
  • [ ] Inspect the final entitlements.
  • [ ] Verify the app and every reported nested object with codesign.
  • [ ] Submit the exact distribution artifact.
  • [ ] Save the submission ID and JSON log.
  • [ ] Confirm the final status.
  • [ ] Staple every supported final object.
  • [ ] Validate the stapled object.
  • [ ] Download the artifact through the real distribution path.
  • [ ] Run spctl and launch it under a clean test account.
  • [ ] Store the redacted results with the build identifier.

For ongoing releases, keep the certificate, private key, Keychain profile, Xcode Command Line Tools, signing scripts, and log archive under one documented environment. Apple supports scripted workflows through notarytool and stapler, and also provides the Notary API for teams that need a service-based integration.

If your local Mac cannot stay available for repeated signing and notarization, a remote Mac can be a better fit than repeatedly repairing a disposable build image. The important requirement is not a generic “cloud Mac” label. It is persistent access to the signing keychain, the approved toolchain, the release scripts, and the redacted evidence from every stage. You can review CALMVPS Mac rental plans or remote Mac ordering options after you define those acceptance requirements.

A one-time repair is enough when you only need to ship one corrected build. If you release regularly, a laptop-based workflow often leaves three operational gaps: the Mac may be offline, the signing keychain may not be available to automation, and failed logs may disappear with the temporary environment. In that case, renting a Mac from CALMVPS gives you a more controllable release host without requiring you to buy a separate machine solely for signing, notarization, and packaging.