git-ecosystem/git-credential-manager · error · InteropException
ErrorSecInteractionNotAllowed
ErrorSecInteractionNotAllowed
Error message
Interaction with the Security Server is not allowed.
What it means
InteropException thrown by SecurityFramework.ThrowIfError when the macOS Security framework returns errSecInteractionNotAllowed (-25308). It means the requested keychain operation needed to talk to the Security Server (prompt the user, unlock the keychain) but the current session/process context forbids user interaction. The library cannot complete the operation without a UI, so it throws instead of hanging.
Solutions
- Unlock the keychain non-interactively first: `security unlock-keychain -p <password> <keychain>` or SecKeychainUnlock with the password.
- Run the process inside a logged-in GUI session (e.g. a LaunchAgent with LimitLoadToSessionType=Aqua) rather than a system daemon or SSH session.
- Partition the keychain for CI (`security set-key-partition-list -S apple-tool:,apple: -k <password> <keychain>`) so items are readable without prompts.
- For items requiring biometric/password auth (Touch ID / kSecAccessControl), drop that requirement or gate the operation on a UI-capable context.
- Verify the process user matches the keychain owner; root or other users cannot be granted interactive access to a login keychain.
Example fix
// before: CI daemon reads a locked login keychain and throws err = SecKeychainFindGenericPassword(null, serviceLength, service, accountLength, account, out length, out data, IntPtr.Zero); SecurityFramework.ThrowIfError(err); // -25308, no UI available to unlock // after: pre-unlock the keychain non-interactively in CI setup // security unlock-keychain -p "$KEYCHAIN_PASSWORD" login.keychain // security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" login.keychain err = SecKeychainFindGenericPassword(null, serviceLength, service, accountLength, account, out length, out data, IntPtr.Zero); SecurityFramework.ThrowIfError(err);
Defensive patterns
Strategy: retry
Validate before calling
// Verify the process can access the keychain without UI before touching it
var (exitCode, _) = Run("security", "show-keychain-info login.keychain");
bool keychainAccessibleNonInteractively = exitCode == 0;
if (!keychainAccessibleNonInteractively) throw new InvalidOperationException("Unlock the keychain before running: security unlock-keychain -p <pwd> login.keychain"); Type guard
static bool IsSecInteractionNotAllowed(InteropException ex) => ex.ErrorCode == -25308; // errSecInteractionNotAllowed
Try / catch
try
{
credential = ReadCredentialFromKeychain(service, account);
}
catch (InteropException ex) when (ex.ErrorCode == -25308)
{
// No UI available (SSH/daemon/CI): unlock non-interactively, then retry once.
UnlockKeychainNonInteractive(keychainPassword);
credential = ReadCredentialFromKeychain(service, account);
} Prevention
- In CI, unlock the keychain in a before_script and set the partition list (`security set-key-partition-list -S apple-tool:,apple: -k <pwd>`).
- Run background consumers as LaunchAgents in the Aqua session, not as root LaunchDaemons.
- Avoid Touch ID / user-presence access-control flags for items read by headless services.
- Detect headless/SSH contexts early and fail fast with a clear setup message instead of a raw interop error.
When it happens
Trigger: Keychain reads (SecKeychainFindGenericPassword, SecItemCopyMatching) on a locked keychain from a process with no UI access: SSH session, launchd daemon, CI runner, or app running as another user; SecItemCopyMatching with kSecUseAuthenticationUIDisallow while the item requires user presence; background service attempting to access items whose ACL requires confirmation.
Common situations: CI/CD pipelines unlocking the login keychain non-interactively; macOS background daemons/agents started before login window; SSH remote builds touching keychain-backed settings; apps sandboxed or running as root where Security Server denies UI; Headless macOS VMs in test farms.
Related errors
- ErrorSecNoSuchKeychain
- ErrorSecInvalidKeychain
- ErrorSecAuthFailed
- ErrorSecDuplicateItem
- ErrorSecItemNotFound
AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11).
Data as JSON: /api/errors/c05498440835e1ee.
Report an issue: GitHub.
Appendix: source
Thrown at src/Core/Interop/MacOS/Native/SecurityFramework.cs:152
public static void ThrowIfError(int error, string defaultErrorMessage = "Unknown error.")
{
switch (error)
{
case OK:
return;
case ErrorSecNoSuchKeychain:
throw new InteropException("The keychain does not exist.", error);
case ErrorSecInvalidKeychain:
throw new InteropException("The keychain is not valid.", error);
case ErrorSecAuthFailed:
throw new InteropException("Authorization/Authentication failed.", error);
case ErrorSecDuplicateItem:
throw new InteropException("The item already exists.", error);
case ErrorSecItemNotFound:
throw new InteropException("The item cannot be found.", error);
case ErrorSecInteractionNotAllowed:
throw new InteropException("Interaction with the Security Server is not allowed.", error);
case ErrorSecInteractionRequired:
throw new InteropException("User interaction is required.", error);
case ErrorSecNoSuchAttr:
throw new InteropException("The attribute does not exist.", error);
default:
throw new InteropException(defaultErrorMessage, error);
}
}
}
[Flags]
public enum SessionAttributeBits
{
SessionIsRoot = 0x0001,
SessionHasGraphicAccess = 0x0010,
SessionHasTty = 0x0020,
SessionIsRemote = 0x1000,
}View on GitHub (pinned to e8ce762cd0)