errSecInternalComponent is one of those Apple status codes that means almost nothing on its own. It is a generic failure out of the Security framework, and Apple's documentation offers no specifics. In the narrow case where codesign emits it, though, the cause is reliably the same: the tool asked the keychain for a private key and was refused.
You will essentially only see it on build machines. On a Mac with a logged-in desktop session the same underlying condition produces a dialog box asking for permission instead. No session means no dialog, and no dialog means the request simply fails.
It also tends to appear halfway through a pipeline rather than at the start, which is what makes it feel random. The import step succeeds, the identity lists correctly, and then the archive fails twenty minutes later. Nothing changed in between except that a lock timer expired or the build moved to a step running as a different user. Worth knowing before you start suspecting the certificate itself, which is almost never at fault here.
The three things that cause it
- The keychain is locked
- A keychain you created in an earlier step, or one that auto-locked because its lock timeout was shorter than the build. A locked keychain hands out nothing.
- The key has no partition list
- An imported key starts with an empty partition list, which means no tool is pre-approved to use it non-interactively. The -T flag on security import is not sufficient by itself on modern macOS.
- The job is running over SSH
- An SSH session does not unlock the user's login keychain, even though logging in at the physical machine does. A pipeline that works when someone is sat in front of the Mac and fails from a remote agent is almost always this.
The fix, in the order it has to happen
These steps are order-dependent. Setting the partition list on a locked keychain will not work, and unlocking after codesign has already failed does not retroactively help. Put all of it in the job, before the build.
KEYCHAIN="$HOME/Library/Keychains/build.keychain-db" KEYCHAIN_PASSWORD=$(uuidgen) security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN" # Disable the lock timeout entirely; the keychain is deleted at job end anyway security set-keychain-settings "$KEYCHAIN" security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN" security import signing/dist.p12 \ -k "$KEYCHAIN" \ -P "$P12_PASSWORD" \ -A \ -T /usr/bin/codesign \ -T /usr/bin/security # The step that actually stops errSecInternalComponent security set-key-partition-list \ -S apple-tool:,apple:,codesign: \ -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN" security list-keychains -d user -s "$KEYCHAIN" login.keychain security default-keychain -s "$KEYCHAIN"
Checking your work
Two commands tell you whether signing will succeed, and both are cheap enough to leave in the pipeline permanently.
# Is the identity visible and usable? security find-identity -v -p codesigning "$KEYCHAIN" # Does an actual signature succeed without a prompt? codesign --force --sign "Apple Distribution: Acme Corp (ABCDE12345)" \ --keychain "$KEYCHAIN" \ /tmp/scratch.app
If find-identity lists the identity but the signature still fails, the partition list is the remaining suspect. If find-identity lists nothing, the problem is earlier: the import did not land where you think, or the keychain is not in the search list.
Pointing the build at the right keychain
Even a correctly configured keychain does nothing if xcodebuild signs against a different one. Two settings make it explicit, and on a shared runner with more than one keychain in play they are worth setting rather than trusting the search order.
xcodebuild archive \ -scheme MyApp \ -archivePath build/MyApp.xcarchive \ OTHER_CODE_SIGN_FLAGS="--keychain $KEYCHAIN"
Related messages with the same root cause
- The interactive form of the same refusal: codesign wants to access key in your keychain. Same partition list, different presentation.
- "User interaction is not allowed" from codesign or from the security command. Usually a locked keychain specifically, rather than the partition list.
- "The specified item could not be found in the keychain" during export. The identity is genuinely absent, not merely inaccessible.
security delete-keychain "$KEYCHAIN" || true