---
updatedAt: 2026-10-20T01:04:53.000Z
agentTools:
  projectIndex: https://docs.setapp.com/llms.txt
---

# Build validation findings

Setapp checks each macOS build that you upload in the developer account. This page explains each finding that the checks can return. The developer account shows the code of each finding, for example `icon.edge_margin`, and a **View instructions** link to its section on this page.

You can give this page to an AI assistant. The page is also available as Markdown: [build-validation-findings.md](https://docs.setapp.com/docs/build-validation-findings.md).

## Results

Each finding has one of these results:

| Result           | What it means                                              | What to do                                                                                                  |
| :--------------- | :--------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |
| Blocks the build | The build cannot go to review.                             | Fix the problem and upload a new build.                                                                     |
| Manual review    | The check could not decide. A reviewer examines the build. | Submit the version. If the reviewer finds a problem, you get a message.                                     |
| Warning          | The build is not blocked.                                  | Fix the problem in a later build. Some warnings ask you for an explanation in Comments for the review team. |

## Order of the checks

Some checks run only when other checks pass. When you fix a problem, the next build can show findings that the first build did not show.

* If the archive check blocks the build, or the archive could not be inspected, Setapp does not run the other checks.
* If Info.plist cannot be read, Setapp does not check the icon, Setapp Framework, the architectures and the code signature.
* If the executable is missing, Setapp does not check Setapp Framework, the architectures and the code signature.
* Setapp checks the notarization only when the code signature check passes or has only warnings.
* The security scan runs whenever Setapp could extract the app, also when other checks found problems.
* The malware scan runs only when no other check blocks the build or needs a manual review.

## Archive

### archive.unreadable

**The archive cannot be read.** Result: blocks the build.

* **Rule:** The file is not a valid ZIP archive, or an entry in the archive is damaged and does not decompress.
* **Check on your Mac:** `unzip -t MyApp.zip` must show No errors detected.
* **Fix:** Compress the app again with Finder or with `ditto -c -k --keepParent MyApp.app MyApp.zip`, and upload a new build.

### archive.no\_app\_bundle

**The archive has no app.** Result: blocks the build.

* **Rule:** The archive must contain exactly one .app bundle, at the top level or in one folder at the top level. An app inside another app, for example a helper app, does not count. The finding also occurs when the archive has two or more .app bundles at these levels.
* **Fix:** Put one .app bundle at the top level of the ZIP archive, and upload a new build.
* **API values:** `bundles`, the number of .app bundles that Setapp found.

### archive.unsafe\_entry

**The archive has an unsafe entry.** Result: blocks the build.

* **Rule:** An entry has one of these problems:
  * The name is empty, starts with `/`, or has a line break or a NUL character.
  * The path has a `..` part.
  * A symbolic link has an absolute target, a target with a line break or a NUL character, or a target longer than 4096 bytes.
  * A symbolic link points outside the .app folder. This rule applies to every symbolic link in the archive.
  * A symbolic link is in a folder that is also a symbolic link, or a chain of links ends outside the app.
* **Check on your Mac:** `find MyApp.app -type l -ls` lists the symbolic links and their targets.
* **Fix:** Use relative symbolic links that stay inside the app. Remove the unsafe entry, compress the app again with `ditto`, and upload a new build.
* **API values:** `path`, and `target` for a symbolic link.

### archive.too\_large

**The archive is too large.** Result: blocks the build.

* **Rule:** One of these limits is exceeded:
  * The archive is larger than 5 GiB (5 368 709 120 bytes).
  * The expanded archive is larger than 10 GiB (10 737 418 240 bytes).
  * The archive has more than 50 000 entries. Entries in `__MACOSX` and `._` files do not count.
* **Check on your Mac:** `zipinfo -t MyApp.zip` shows the number of entries and the expanded size.
* **Fix:** Remove the files that the app does not use, for example debug symbols or unused resources, and upload a new build.
* **API values:** `compressedSize`, `entries` or `expandedSize`.

### archive.checksum\_mismatch

**The archive checksum does not match.** Result: blocks the build.

* **Rule:** Setapp compares the SHA-256 of the uploaded file with the checksum that was given when the build was created. This check runs only when a checksum was given. When this finding occurs, Setapp does not run the other checks of the app, except the security scan.
* **Check on your Mac:** `shasum -a 256 MyApp.zip` shows the checksum in lowercase hexadecimal.
* **Fix:** Upload the file that the checksum was computed for, or create a new build with the correct checksum.
* **API values:** `expected`, `actual`.

### archive.not\_inspected

**The archive could not be inspected.** Result: manual review.

* **Rule:** Setapp could not download or open the archive after 3 attempts. For example, the uploaded file is larger than the size that was given when the build was created. Setapp does not run the other checks.
* **Fix:** No action is necessary. A reviewer examines the build. If the reviewer finds a problem, you get a message.

## Info.plist

### bundle.plist\_unreadable

**Info.plist cannot be read.** Result: blocks the build.

* **Rule:** The file `Contents/Info.plist` is missing, is empty, or is not a valid property list in XML, binary or OpenStep format.
* **Check on your Mac:** `plutil -lint MyApp.app/Contents/Info.plist` must show OK.
* **Fix:** Make sure that the build writes a valid Info.plist, and upload a new build.

### bundle.required\_key\_missing

**A required Info.plist key is missing.** Result: blocks the build.

* **Rule:** Info.plist must have each of these keys, with a string value that is not empty: `CFBundleIdentifier`, `CFBundleVersion`, `CFBundleShortVersionString`, `CFBundleExecutable`, `CFBundleName`.
* **Check on your Mac:** `plutil -extract CFBundleName raw MyApp.app/Contents/Info.plist` shows the value of one key. Do this for each key.
* **Fix:** Add the missing key to Info.plist, and upload a new build.
* **API values:** `keys`, the missing keys.

### bundle.id\_invalid\_format

**The bundle ID has an incorrect format.** Result: blocks the build.

* **Rule:** `CFBundleIdentifier` can contain only Latin letters, digits, dots and hyphens.
* **Fix:** Set `CFBundleIdentifier` to the Setapp bundle ID of the app, and upload a new build.
* **API values:** `found`.

### bundle.id\_mismatch

**The bundle ID does not match the application.** Result: blocks the build.

* **Rule:** `CFBundleIdentifier` must be the same as the bundle ID of the application in Setapp. The comparison is case-sensitive.
* **Check on your Mac:** `plutil -extract CFBundleIdentifier raw MyApp.app/Contents/Info.plist`
* **Fix:** Set `CFBundleIdentifier` to the bundle ID of the application in Setapp, and upload a new build.
* **API values:** `found`, `expected`.

### bundle.version\_invalid

**The build number is not valid.** Result: blocks the build.

* **Rule:** `CFBundleVersion` can contain only numbers separated by dots, for example `1204` or `3.2.1`, and can have up to 50 characters. When the key is missing, the finding is `bundle.required_key_missing`.
* **Fix:** Set `CFBundleVersion` to a number, for example `1204`, and upload a new build.
* **API values:** `found`.

### bundle.short\_version\_invalid

**The version is not valid.** Result: blocks the build.

* **Rule:** `CFBundleShortVersionString` can contain only numbers separated by dots, for example `3.2.1`, and can have up to 50 characters. When the key is missing, the finding is `bundle.required_key_missing`.
* **Fix:** Set `CFBundleShortVersionString` to a version, for example `3.2.1`, and upload a new build.
* **API values:** `found`.

### bundle.name\_mismatch

**The app name does not match the bundle.** Result: blocks the build.

* **Rule:** `CFBundleName` must be the same as the name of the .app folder without .app. The comparison is case-sensitive. For example, the folder `My App.app` needs the `CFBundleName` value `My App`.
* **Fix:** Make `CFBundleName` the same as the name of the .app folder, and upload a new build.
* **API values:** `found`, `expected`.

### bundle.executable\_missing

**The executable is missing.** Result: blocks the build.

* **Rule:** The file that `CFBundleExecutable` names must be in `Contents/MacOS` and must be a regular file. A symbolic link to a regular file is permitted. When this finding occurs, Setapp does not check Setapp Framework, the architectures and the code signature.
* **Check on your Mac:** `plutil -extract CFBundleExecutable raw MyApp.app/Contents/Info.plist` shows the name. Then `ls -l MyApp.app/Contents/MacOS/` must list a file with this name.
* **Fix:** Make sure that the build includes the executable, and upload a new build.
* **API values:** `executable`.

## Icon

Setapp finds the icon in this order:

1. Setapp reads `CFBundleIconFile` in Info.plist. Below, `name` is this value without .icns.
2. Setapp looks for a PNG file and uses the first file with a larger side of 1024 pixels or more:
   * `AppIcon.png` next to the .app in the archive. This file can be up to 20 MiB.
   * `name.png` next to the .app in the archive.
   * `name.png` in `Contents/Resources`, then in each folder in `Contents`, then in `Contents`.
3. When no PNG file qualifies, Setapp uses `name.icns` from the same folders and takes its widest PNG image.

The simplest setup: put `AppIcon.png` of 1024 × 1024 pixels next to the .app in the archive, and set `CFBundleIconFile`.

### icon.missing

**The app has no icon.** Result: blocks the build.

* **Rule:** `CFBundleIconFile` is not set, or Setapp found no PNG icon of 1024 pixels or more and no .icns file with this name. `AppIcon.png` alone is not sufficient: Setapp also needs `CFBundleIconFile`.
* **Fix:** Put `AppIcon.png` of 1024 × 1024 pixels next to the app in the archive, name the .icns file in `CFBundleIconFile`, and upload a new build.
* **API values:** `iconFile`, the value of `CFBundleIconFile`. It is empty when the key is not set.

### icon.too\_small

**The icon is too small.** Result: blocks the build.

* **Rule:** Setapp found no PNG icon of 1024 pixels or more, and the widest image in the .icns file is narrower than 1024 pixels.
* **Check on your Mac:** `sips -g pixelWidth -g pixelHeight AppIcon.png` shows the size of a PNG file. `iconutil -c iconset MyIcon.icns` extracts the images of an .icns file.
* **Fix:** Put `AppIcon.png` of 1024 × 1024 pixels next to the app in the archive, and upload a new build.
* **API values:** `largest`, `minimum`.

### icon.too\_large

**The icon is too large.** Result: blocks the build.

* **Rule:** The PNG icon that Setapp uses is wider or taller than 1024 pixels, for example an `AppIcon.png` of 2048 × 2048 pixels.
* **Fix:** Put `AppIcon.png` of 1024 × 1024 pixels next to the app in the archive, and upload a new build.
* **API values:** `largest`, `maximum`.

### icon.not\_square

**The icon is not square.** Result: blocks the build.

* **Rule:** The width and the height of the icon are not the same. With the two rules above, only an icon of exactly 1024 × 1024 pixels passes.
* **Fix:** Put `AppIcon.png` of 1024 × 1024 pixels next to the app in the archive, and upload a new build.
* **API values:** `width`, `height`.

### icon.edge\_margin

**The icon design is too close to the edge.** Result: blocks the build.

* **Rule:** Setapp finds the pixels of the design, which are the pixels with an opacity of about 50 % or more. Setapp then measures the distance from the box around these pixels to each edge of the canvas. When the smallest distance is less than 50 pixels, the build is blocked. Setapp asks for a margin of 100 pixels. A fully opaque square icon has a margin of 0 pixels.
* **Fix:** Place the icon design inside a frame of 824 × 824 pixels in the middle of the canvas, and upload a new build.
* **API values:** `margin`, the smallest distance in pixels, and `expected`.

### icon.unreadable

**The icon cannot be read.** Result: manual review.

* **Rule:** The .icns file has only images in old formats, for example JPEG 2000, and no PNG image.
* **Fix:** No upload is necessary for this finding. To let the check pass in a later build, save the .icns file with PNG images, for example with `iconutil -c icns MyIcon.iconset`.
* **API values:** `frames`, the number of images in old formats.

### icon.invalid

**The icon file is damaged.** Result: blocks the build.

* **Rule:** The file is not a valid .icns file, it has no images, or all its PNG images are damaged.
* **Check on your Mac:** `iconutil -c iconset MyIcon.icns` extracts the images of a valid file.
* **Fix:** Export the icon again as an .icns file with PNG images, for example with `iconutil -c icns MyIcon.iconset`, and upload a new build.
* **API values:** `iconFile`.

### icon.asset\_catalog\_unsupported

**The asset catalog icon needs manual review.** Result: manual review.

* **Rule:** The app declares its icon in `CFBundleIconName` and in a `Contents/Resources/Assets.car` file, and Setapp found no icon file for `CFBundleIconFile`. Setapp cannot inspect icons in an asset catalog yet.
* **Fix:** No upload is necessary for this finding. A reviewer examines the icon. To let Setapp check the icon automatically, also put `AppIcon.png` of 1024 × 1024 pixels next to the app and set `CFBundleIconFile`.
* **API values:** `iconName`.

## Setapp Framework

### framework.version\_missing

**Setapp Framework is not found.** Result: blocks the build.

* **Rule:** Setapp looks for the version marker of Setapp Framework, `__scv__` followed by a version number. Setapp looks in the main executable, and in an Electron app also in the files `node_setapp_binding.node`, `setapp.node`, `app.asar`, `app-arm64.asar` and `app-x64.asar` in `Contents`.
* **Check on your Mac:** `strings -a MyApp.app/Contents/MacOS/MyApp | grep __scv__` must show the marker.
* **Fix:** Add [Setapp Framework](/docs/installing-the-framework-1) to the app, and upload a new build. When the finding lists a .debug.dylib file, the build is a Debug build. Archive a Release build.
* **API values:** `debugDylibs`, the .debug.dylib files in `Contents/MacOS`.

### framework.obsolete

**Setapp Framework is obsolete.** Result: blocks the build.

* **Rule:** The version of Setapp Framework is earlier than 4.0.0.
* **Fix:** Update Setapp Framework to the latest version, and upload a new build.
* **API values:** `found`, `minimum`.

### framework.outdated

**Setapp Framework is outdated.** Result: warning.

* **Rule:** The version of Setapp Framework is 4.0.0 or later, but earlier than 5.5.1. Earlier versions do not have the latest fixes for usage reports.
* **Fix:** Update Setapp Framework to the latest version in a later build.
* **API values:** `found`, `minimum`.

### framework.security\_policy\_missing

**The update security policy is missing.** Result: blocks the build.

* **Rule:** Info.plist must have the key `NSUpdateSecurityPolicy` with this structure:

  ```xml
  <key>NSUpdateSecurityPolicy</key>
  <dict>
      <key>AllowProcesses</key>
      <dict>
          <key>MEHY5QF425</key>
          <array>
              <string>com.setapp.DesktopClient.SetappAgent</string>
          </array>
      </dict>
  </dict>
  ```

* **Fix:** Add `NSUpdateSecurityPolicy` to Info.plist, and upload a new build.

* **API values:** `teamId`, `process`.

### framework.restricted\_dependency

**The app includes a restricted framework.** Result: warning.

* **Rule:** The main executable links, or `Contents/Frameworks` contains, one of these frameworks: Sparkle, Paddle, DevMateKit, DevMateActivation, Squirrel. Setapp updates and licenses the app, so the Setapp build does not need them.
* **Check on your Mac:** `otool -L MyApp.app/Contents/MacOS/MyApp` and `ls MyApp.app/Contents/Frameworks`
* **Fix:** Remove the framework from the Setapp build of the app.
* **API values:** `frameworks`.

## Architectures

### architecture.unsupported\_name

**An architecture name is not supported.** Result: blocks the build.

* **Rule:** Each value in `MPSupportedArchitectures` must be exactly `arm64` or `x86_64`. The comparison is case-sensitive.
* **Fix:** Correct `MPSupportedArchitectures` in Info.plist, and upload a new build. See [Specify supported architectures](/docs/specify-supported-architectures).
* **API values:** `found`, `permitted`.

### architecture.mismatch

**The architectures do not match.** Result: warning.

* **Rule:** The values in `MPSupportedArchitectures` are not the same as the architectures of the main executable. `arm64e` counts as `arm64`. When the key is not set, Setapp does not do this check.
* **Check on your Mac:** `lipo -archs MyApp.app/Contents/MacOS/MyApp`
* **Fix:** Make `MPSupportedArchitectures` agree with the architectures of the executable.
* **API values:** `declared`, `found`.

## Code signature

Setapp verifies the code signature in the same way as `codesign`: the page hashes of each architecture, Info.plist, the resource seal in `_CodeSignature/CodeResources`, the nested code, and the certificate chain to Apple. The certificate must be a Developer ID Application certificate that was valid at the signing time.

### signature.missing

**The app is not code-signed.** Result: blocks the build.

* **Rule:** The main executable is not a Mach-O file, or no architecture in it is signed.
* **Check on your Mac:** `codesign -dvv MyApp.app`. The message code object is not signed at all means this finding.
* **Fix:** Sign the app with your Developer ID Application certificate, and upload a new build.
* **API values:** `detail`.

### signature.invalid

**The code signature is not valid.** Result: manual review. The build cannot pass the automatic checks.

* **Rule:** The code signature does not agree with the contents of the app. The API value `reason` tells what is wrong:
  * `adhoc`: the app has an ad hoc signature without a certificate.
  * `executable`: a page hash, the signature of an architecture, the requirements or the entitlements do not match.
  * `info_plist`: Info.plist changed after signing.
  * `resources_seal`: `_CodeSignature/CodeResources` is missing or does not match.
  * `resource`: a file changed after signing, is missing, or is not in the seal, or nested code changed or is not signed.
  * `cms`: the signature data does not verify, or it does not have exactly one signer.
  * `certificate`: the chain does not reach an Apple root certificate, a certificate was not valid at the signing time, or the certificate is not a Developer ID Application certificate, for example an Apple Development or a Mac App Store certificate.
* **Check on your Mac:** `codesign --verify --deep --strict --verbose=2 MyApp.app`. Then `codesign -dvv MyApp.app` must show Authority=Developer ID Application.
* **Fix:** Sign the app again with your Developer ID Application certificate, and do not change files after signing. Compress the app with Finder or `ditto`. The `zip` command without `-y` copies the targets of symbolic links and breaks the seal. Upload a new build.
* **API values:** `reason`, `path`, `detail`. The API returns up to 20 findings, then one finding with the reason `more` and a `count`.

### signature.unverifiable

**The code signature cannot be verified.** Result: manual review.

* **Rule:** Setapp cannot read the signature, for example because a part of it is damaged, or because a file could not be read.
* **Check on your Mac:** `codesign --verify --deep --strict --verbose=2 MyApp.app`
* **Fix:** No action is necessary. If the reviewer finds a problem, you get a message.
* **API values:** `detail`.

## Notarization

Setapp checks the notarization only when the code signature check passes or has only warnings. Setapp asks the Apple notarization service, the same service that `stapler` and Gatekeeper use, for a ticket for the code of each architecture.

### notarization.missing

**The app is not notarized.** Result: blocks the build.

* **Rule:** Apple has no notarization ticket for any architecture of the app.
* **Check on your Mac:** `spctl --assess --type execute -vv MyApp.app` must show source=Notarized Developer ID.
* **Fix:** Notarize the app with `xcrun notarytool submit`, staple the ticket with `xcrun stapler staple MyApp.app`, compress the app again, and upload a new build.

### notarization.unstapled

**The notarization ticket is not stapled.** Result: warning.

* **Rule:** Apple notarized the app, but the ticket is not attached to the app. Without a stapled ticket, macOS must go online to verify the app.
* **Check on your Mac:** `xcrun stapler validate MyApp.app`
* **Fix:** Staple the ticket with `xcrun stapler staple MyApp.app`, compress the app again after stapling, and upload a new build.

### notarization.lookup\_failed

**The notarization cannot be verified.** Result: manual review.

* **Rule:** Setapp did not get an answer from the Apple notarization service after 5 attempts.
* **Fix:** No action is necessary. If the reviewer finds a problem, you get a message.
* **API values:** `reason` with the value `lookup_unavailable`, when Setapp could not ask the service.

## Security scan

### codeanalysis.found

**Tell us why the app uses these capabilities.** Result: warning.

* **Rule:** The Setapp security scan found code that uses sensitive capabilities. This does not stop the review. When a reviewer approved an earlier build of the app, the finding lists only the capabilities that the approved build did not use.
* **Fix:** In [Comments for the review team](/docs/submitting-apps-for-review#comments-for-the-review-team) on the version page, explain why the app needs each capability. The reviewer uses your explanation to review the version.
* **API values:** `rules`, the capabilities that the scan found. Each item has `rule`, `description`, `count` and up to 5 `files`.

### codeanalysis.incomplete

**The security scan did not complete.** Result: warning.

* **Rule:** The Setapp security scan did not return a result.
* **Fix:** No action is necessary.
* **API values:** `reason`: `scanner_unavailable`, `app_unavailable` or `scan_failed`.

## Malware scan

The malware scan runs only when no other check blocks the build or needs a manual review. Setapp looks up the SHA-256 of the archive in a malware scanning service, and uploads the archive when the service does not know it.

### malware.detected

**A malware scanner flagged the archive.** Result: manual review.

* **Rule:** At least one scanner reports the archive as malicious. Scanners can report false positives, so a reviewer examines the build and the scan report.
* **Fix:** No action is necessary. If the reviewer confirms the threat, you get a message. If you know why a scanner flags the app, explain it in [Comments for the review team](/docs/submitting-apps-for-review#comments-for-the-review-team).
* **API values:** `count`, `malicious`, `suspicious`, `undetected`, `harmless`, `detections` (each flagged scanner with `engine`, `category` and `result`), `permalink` to the scan report.

### malware.suspicious

**A malware scanner marked the archive as suspicious.** Result: manual review.

* **Rule:** No scanner reports the archive as malicious, but at least one scanner reports it as suspicious.
* **Fix:** No action is necessary. A reviewer examines the build. If the reviewer finds a problem, you get a message.
* **API values:** `count`, `malicious`, `suspicious`, `undetected`, `harmless`, `detections` (each flagged scanner with `engine`, `category` and `result`), `permalink` to the scan report.

### malware.scan\_incomplete

**The malware scan did not complete.** Result: manual review.

* **Rule:** The malware scan did not return a result.
* **Fix:** No action is necessary. A reviewer examines the build.
* **API values:** `reason`: `scanner_unavailable`, `lookup_failed`, `upload_disabled` or `upload_failed`.

### malware.file\_too\_large

**The archive is too large for the malware scan.** Result: manual review.

* **Rule:** The malware scanning service does not know the archive, and the archive is larger than 650 MiB (681 574 400 bytes), the largest file that the service accepts.
* **Fix:** No action is necessary. A reviewer examines the build.
* **API values:** `size`, `maximum`.