You know that sinking feeling in your stomach. That horrible emotion that you know that something has gone wrong, seriously wrong, and you’re going to be facing a mountain of pain. That terror that’s even worse than your significant other sitting you down saying “we need to talk”. It’s this:
That’s right. Something has gone wrong with signing, provisioning, or certificates, or something.
Now you, as the individual in charge of putting out a beta (or enterprise) release, have to fix it. Over the past numerous months I’ve had to set up some ad-hoc beta builds for OTA (over the air) delivery, as well as distributing builds with App47, an enterprise application management system and TestFlight, and I knew I was in for some suffering when I got that alert on my first installation test.
What usually happens is hours of flailing around, Trying Stuff, begging Uncle Google for advice, and then magically It Starts Working, in which case you step away from the keyboard, commit the current state of your Xcode project, and find a bottle of single malt to crawl into. This time before hitting the Glen Breton, I’m writing down what I discovered.
The console log on your device might have some useful information on it. Before trying your install, make sure your device is actually being shown on the console in the Xcode organizer. Sometimes I select the console, or look at the Organizer window funny, and the console view goes blank, refusing to show any new content. If your console goes blank, wave a dead chicken over it by clicking off the console and back on it a couple of times. When you get a screenful of text, try installing your program. You hopefully will see something like this.
installd <Error>: entitlement 'get-task-allow' has value not permitted by a provisioning profile installd <Error>: entitlement 'application-identifier' has value not permitted by a provisioning profile installd <Error>: 00381000 verify_signer_identity: Could not copy validate signature: -402620394 installd <Error>: 00381000 preflight_application_install: Could not verify executable at /var/tmp/install_staging.RoDpEv/foo_extracted/Payload/Catalog.app itunesstored <Notice>: MobileInstallationInstall: failed with -1 installd <Error>: 00381000 install_application: Could not preflight application install installd <Error>: 00381000 handle_install: API failed installd <Error>: 00381000 send_message: failed to send mach message of 71 bytes: 10000003 installd <Error>: 00381000 send_error: Could not send error response to client
The first two lines are the interesting part. Something is wrong with the provisioning profile. How can you see what’s up? Time to duck down to the command line and peer inside your application.
codesign tool will look at an app and tell you about things relating to signing. It has an extensive man page, but the two variants I use most often show the signing information, and the entitlements baked in to the app.
codesign looks inside of application bundles, not IPA files, so you need to unpack the IPA. Luckily it’s just a zip archive:
% <strong>unzip Catalog.ipa</strong> Archive: Catalog.ipa creating: Payload/ creating: Payload/Catalog.app/ extracting: Payload/Catalog.app/1x1.png creating: Payload/Catalog.app/_CodeSignature/ inflating: Payload/Catalog.app/_CodeSignature/CodeResources inflating: Payload/Catalog.app/Catalog ...
You’ll have a directory called
Payload that contains the app. The program causing me problems today is called
First, take a look at the code signing:
% <strong>codesign -dvvv Payload/Catalog.app</strong> Executable=/Users/markd/junk/Payload/Catalog.app/Catalog Identifier=com.bignerdranch.Catalog Format=bundle with Mach-O thin (armv7) CodeDirectory v=20100 size=2513 flags=0x0(none) hashes=117+5 location=embedded Hash type=sha1 size=20 CDHash=f748ae9eb017fd3b88dce5d55519788239928edc Signature size=4309 Authority=iPhone Distribution: Big Nerd Ranch, Inc Authority=Apple Worldwide Developer Relations Certification Authority Authority=Apple Root CA Signed Time=Aug 30, 2012 7:25:55 PM Info.plist entries=28 Sealed Resources rules=3 files=31 Internal requirements count=1 size=296
The interesting part to me is that yes, it is signed using the Big Nerd Ranch profile I was given for making this release.
So what about the entitlements?
% codesign -d --entitlements - ./Payload/Catalog.app Executable=/Users/markd/junk/Payload/Catalog.app/Catalog <?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>application-identifier</key> <string>9B7AX7DA2G.com.bignerdranch.Catalog</string> <key>get-task-allow</key> <true/> </dict> </plist>
get-task-allow = true? That sounds like one of our problems:
installd <Error>: entitlement 'get-task-allow' has value not permitted by a provisioning profile
It should be set to false. This is an entitlement that tells the launcher that this program can be attached to by other programs, specifically things like debuggers. For things being distributed to real people with a release profile, this needs to be turned off.
How did it get turned on in the first place? One way is to have it explicitly set in an
Entitlements.plist file that’s included in your build. The other way happens automatically: Xcode will set it to true if you sign it with a development profile, and to false if you sign it with a distribution profile.
So that was problem #1 (building with a debug profile and signing the IPA with a release profile), and also an indication of what problem #2 was. I must be using the wrong profile (the one for development) when building the app.
So, what about that profile? What can go wrong with it? You need to make sure that you sign the application at build time with a profile that’s miscible with what you’ll eventually sign the IPA with. This is the application ID from
There was this complaint when trying to install stuff:
entitlement 'application-identifier' has value not permitted by a provisioning profile
So there’s something about this identifier that’s not quite right. The leading chunk of goop is the team ID (also called the bundle seed ID), which kind of looked familiar because it’s my personal ID marklar. I looked in the organizer and noticed the profile I’m using to sign the IPAs has a different leading part:
So, the bundle ID really should be
The only way Xcode will bake the proper ID in there for us is if we sign it with a profile that matches. So after some editing of the signing build settings, I made sure it used the proper profile:
Fixed that stuff, and did a build, signed an IPA, and double-checked my work:
% codesign -d --entitlements - ./Payload/Catalog.app ... <dict> <key>application-identifier</key> <string>E6B2EB2666.com.bignerdranch.Catalog</string> <key>get-task-allow</key> <false/> ...
Much better. The application identifier team ID portion matches what’s in the distribution profile, and get-task-allow is false.
I’d like to say that it only took me five minutes to fix. If I face this again, it might only take five minutes, but it was easily a couple of hours spread out over a couple of days, first wrestling with the third party tool and getting installation failures, then building my own OTA distribution with something like BetaBuilder for easier testing (removing a variable from the system). Once I noticed the info in the log, I hacked the get-task-allow with an entitlement file (which I subsequently removed) to get something working, and then finally fixed all the signing wibbly bits, life was good.