Skip to content

MAS: “${executable}” in bundle “${bundle}” is missing a provisioning profile #9304

@MrOsamah

Description

@MrOsamah

Hello,
I am trying to distribute a MAS app to the App Store Connect using Transporter, when I verify/ deliver the build I get this warning:

Cannot be used with TestFlight because the executable “${executable}” in bundle “${bundle}” is missing a provisioning profile but has an application identifier in its signature. Nested executables are expected to have provisioning profiles with application identifiers matching the identifier in the signature in order to be eligible for TestFlight." (90885)

The issue is that I’m not sure which executable is missing the provisioning profile, preventing me from adding it before packaging and uploading the app using Transporter.

I checked if I signed all the Electron apps using codesign:

> codesign --verify --deep --strict --verbose=2 My\ App.app
--prepared:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (Plugin).app
--prepared:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper.app
--prepared:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (Renderer).app
--validated:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (Plugin).app
--validated:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper.app
--prepared:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Library/LoginItems/My App Login Helper.app
--validated:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (Renderer).app
--prepared:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (GPU).app
--validated:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Library/LoginItems/My App Login Helper.app
--validated:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (GPU).app
--prepared:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/Electron Framework.framework/Versions/Current/.
--validated:/Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/Electron Framework.framework/Versions/Current/.
My App.app: valid on disk
My App.app: satisfies its Designated Requirement

Also I checked if they have embedded provision profile:

> find My\ App.app -name embedded.provisionprofile
My App.app/Contents/Library/LoginItems/My App Login Helper.app/Contents/embedded.provisionprofile
My App.app/Contents/embedded.provisionprofile
My App.app/Contents/Frameworks/My App Helper (Plugin).app/Contents/embedded.provisionprofile
My App.app/Contents/Frameworks/My App Helper (Renderer).app/Contents/embedded.provisionprofile
My App.app/Contents/Frameworks/My App Helper (GPU).app/Contents/embedded.provisionprofile
My App.app/Contents/Frameworks/My App Helper.app/Contents/embedded.provisionprofile

And as you can see all Electron apps are signed and have an embedded provision profile, given my configuration below, has anyone faced a similar issue or know how can I resolve the Transporter error?

Terminal output:

> electron-builder  --config electron-builder.cjs -m mas --universal

  • electron-builder  version=26.0.12 os=24.2.0
  • loaded configuration  file=/Users/user/myapp/electron-builder.cjs
  • author is missed in the package.json  appPackageFile=/Users/user/myapp/package.json
  • writing effective config  file=dist/builder-effective-config.yaml
  • rebuilding native dependencies  [email protected], [email protected], [email protected], [email protected] platform=darwin arch=x64
  • install prebuilt binary  name=sqlite3 version=5.1.7 platform=darwin arch=x64 napi=
34m• packaging       platform=mas arch=x64 electron=35.7.4 appOutDir=dist/mas-universal-x64-temp
  • rebuilding native dependencies  [email protected], [email protected], [email protected], [email protected] platform=darwin arch=arm64
  • install prebuilt binary  name=sqlite3 version=5.1.7 platform=darwin arch=arm64 napi=
34m• packaging       platform=mas arch=arm64 electron=35.7.4 appOutDir=dist/mas-universal-arm64-temp
  • packaging       platform=mas arch=universal electron=35.7.4 appOutDir=dist/mas-universal
  • signing         file=dist/mas-universal/My App.app platform=darwin type=distribution identityName=Developer ID Application: DELETED identityHash=DELETED provisioningProfile=none
  • notarization successful
Embedding profile in Frameworks: /Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (GPU).app
Embedding profile in Frameworks: /Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (Plugin).app
Embedding profile in Frameworks: /Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper (Renderer).app
Embedding profile in Frameworks: /Users/user/myapp/dist/mas-universal/My App.app/Contents/Frameworks/My App Helper.app
Embedding profile in Library: /Users/user/myapp/dist/mas-universal/My App.app/Contents/Library/LoginItems/My App Login Helper.app
  • signing         file=dist/mas-universal/My App.app platform=mas type=distribution identityName=Apple Distribution: DELETED identityHash=DELETED provisioningProfile=mas/myapp_desktop.provisionprofile

package.json (some irrelevant packages have been removed):

{
  "name": "my-app",
  "version": "1.0.0",
  "private": true,
  "main": "build/main.js",
  "description": "My App",
  "scripts": {
    "next:dev": "next dev --turbo",
    "next:build1": "next build",
    "next:build": "node scripts/next-build.mjs",
    "next:start": "next start",
    "postinstall": "electron-builder install-app-deps",
    "electron:dist": "electron-builder  --config electron-builder.cjs",
    "electron:dist:mas-universal": "electron-builder  --config electron-builder.cjs -m mas --universal",
    "electron:dist:ci": "electron-builder --publish always --config electron-builder.cjs  -mwl --x64 --arm64",
    "electron:dist:deb": "electron-builder --linux deb",
    "electron:build": "tsup",
    "build": "run-s next:build electron:build",
    "dist": "run-s build electron:dist",
    "dist:mas-universal": "run-s build electron:dist:mas-universal"
  },
  "dependencies": {
    "electron-context-menu": "^4.1.1",
    "electron-log": "^5.3.4",
    "electron-store": "^8.2.0",
    "electron-updater": "^6.6.2",
    "next": "^14.2.28"
  },
  "devDependencies": {
    "electron": "^35.0.0",
    "electron-builder": "^26.0.12",
    "electron-devtools-installer": "^4.0.0",
    "eslint": "^9.28.0",
    "eslint-config-next": "^15.3.3",
    "eslint-formatter-unix": "^8.40.0",
    "eslint-import-resolver-typescript": "^4.4.3",
    "eslint-plugin-import": "^2.31.0",
    "eslint-plugin-storybook": "^0.11.1",
    "eslint-plugin-tailwindcss": "^3.18.0",
    "identity-obj-proxy": "^3.0.0",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "nodemon": "^3.1.4",
    "npm-run-all": "^4.1.5",
    "postcss": "^8.4.41",
    "storybook": "^8.4.7",
    "tailwindcss": "^3.4.7",
    "ts-jest": "^29.4.1",
    "ts-node": "^10.9.2",
    "tsup": "^8.2.4",
    "typescript": "^5.5.4",
    "typescript-eslint": "^8.34.0"
  },
  "engines": {
    "node": ">=22.0.0"
  }
}

node -v:

v22.17.0

npm -v:

10.9.2

electron-builder config:

require('dotenv').config()

const buildTimestamp = Math.floor(Date.now() / 1000);

module.exports = {
  icon: 'public/icon',
  extraResources: [
    '.env',
  ],
  asar: true,
  productName: process.env.APP_NAME || 'My App',
  executableName: process.env.EXECUTABLE_NAME || 'My App',
  appId: process.env.APP_ID,
  asarUnpack: [
    'node_modules/next',
    'node_modules/@img',
    'node_modules/sharp',
    '**\\*.{node,dll}',
  ],
  files: [
    'build/**/*',
    {
      from: 'out',
      to: 'out',
      filter: ['**/*'],
    },
  ],
  mac: {
    notarize: process.env.ENABLE_NOTARIZE || false,
    identity: process.env.APPLE_IDENTITY,
    target: ['dmg', 'zip', 'mas'],
    bundleVersion: String(buildTimestamp)
  },
  mas: {
    entitlements: "mas/entitlements.mas.plist",
    entitlementsInherit: "mas/entitlements.mas.inherit.plist",
    entitlementsLoginHelper: "mas/entitlements.mas.plist",
    provisioningProfile: "mas/myapp_desktop.provisionprofile",
    hardenedRuntime: true,
    mergeASARs: false, // without this I get Pattern too long if I build the universal app
    notarize: false,
    gatekeeperAssess: true,
    category: "public.app-category.productivity",
    preAutoEntitlements: false, // without this I get validation error from Transporter saying that there are entitlements and profile mismatch
  },
  afterSign: "mas/afterSign.js",
  nativeRebuilder: 'legacy',
}

entitlements.mas.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.application-identifier</key>
<!-- Real values omitted -->
		<string>TEAMID.sa.com.myapp.example</string>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-write</key>
    <true/>
    <key>com.apple.security.app-sandbox</key>
    <true/>
  </dict>
</plist>

entitlements.mas.inherit.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>com.apple.application-identifier</key>
  <!-- Real values omitted -->
		<string>TEAMID.sa.com.myapp.example</string>

    <key>com.apple.security.app-sandbox</key>
    <true/>

    <key>com.apple.security.inherit</key>
    <true/>
</dict>
</plist>

afterSign.js (used to move the provision profile to each one of the electron executables: Helper GPU, Helper Renderer, etc.):

// mas/afterSign.js
const fs = require('fs')
const path = require('path')

exports.default = async function(context) {
  const { appOutDir, packager } = context
  const appName = packager.appInfo.productFilename
  const appDir = path.join(appOutDir, `${appName}.app`)
  const frameworksDir = path.join(appDir, 'Contents/Frameworks')
  const libraryDir = path.join(appDir, 'Contents/Library')

  const masProvisioningProfile = 'mas/myapp_desktop.provisionprofile'

  if (!fs.existsSync(masProvisioningProfile)) {
    console.error(`Provisioning profile not found at ${masProvisioningProfile}`)
    return
  }

  function findAppBundlesRecursively(baseDir) {
    const foundApps = []

    function walk(currentDir) {
      if (!fs.existsSync(currentDir)) return

      const entries = fs.readdirSync(currentDir, { withFileTypes: true })
      for (const entry of entries) {
        const fullPath = path.join(currentDir, entry.name)
        if (entry.isDirectory()) {
          if (entry.name.endsWith('.app')) {
            foundApps.push(fullPath)
          } else {
            walk(fullPath) // recurse deeper
          }
        }
      }
    }

    walk(baseDir)
    return foundApps
  }

  function embedProfileInApps(appDirs, locationName) {
    if (!appDirs.length) {
      console.log(`No .app bundles found in ${locationName}, skipping.`)
      return
    }

    for (const helperAppDir of appDirs) {
      const dest = path.join(helperAppDir, 'Contents/embedded.provisionprofile')
      console.log(`Embedding profile in ${locationName}: ${helperAppDir}`)
      fs.copyFileSync(masProvisioningProfile, dest)
    }
  }

  // 1. Embed in Frameworks helper apps (shallow search)
  if (fs.existsSync(frameworksDir)) {
    const frameworkApps = fs
      .readdirSync(frameworksDir)
      .filter((d) => d.endsWith('.app'))
      .map((d) => path.join(frameworksDir, d))

    embedProfileInApps(frameworkApps, 'Frameworks')
  } else {
    console.log('No Frameworks directory found, skipping.')
  }

  // 2. Embed in *any* helper apps under Library (recursive)
  if (fs.existsSync(libraryDir)) {
    const libraryApps = findAppBundlesRecursively(libraryDir)
    embedProfileInApps(libraryApps, 'Library')
  } else {
    console.log('No Library directory found, skipping.')
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions