git-ecosystem/git-credential-manager · error · InteropException
Unknown error.
Error message
Unknown error.
What it means
ThrowIfError's default case throws InteropException with the generic 'Unknown error.' message when a macOS Security.framework status code has no explicit mapping. It preserves the raw error code so the underlying Sec status can still be diagnosed.
Solutions
- Inspect the InteropException's raw error code and map it to the errSec constant (compare with Apple's Security framework docs).
- Ensure a keychain is available and unlocked in the environment (headless: create/unlock a keychain with `security create-keychain` / `security unlock-keychain`).
- Configure an alternative credential store (cache, plaintext file, GPG/pass) via GCM's credential.credentialStore setting.
- If a common errSec code recurs, extend the switch in ThrowIfError with an explicit case.
Example fix
// before
case ErrorSecNoSuchAttr:
throw new InteropException("The attribute does not exist.", error);
default:
throw new InteropException(defaultErrorMessage, error);
// after
case ErrorSecNoSuchAttr:
throw new InteropException("The attribute does not exist.", error);
case ErrorSecMissingEntitlement:
throw new InteropException("Missing keychain entitlement (check hardening/entitlements).", error);
default:
throw new InteropException($"Unknown security error {error}.", error); Defensive patterns
Strategy: fallback
Validate before calling
// Check a usable keychain exists before invoking the helper: // security show-keychain-info (fails if no default/unlocked keychain)
Type guard
static bool HasUsableKeychain() =>
Environment.OSVersion.Platform == PlatformID.MacOSX &&
Run("security", "show-keychain-info") == 0; Try / catch
try { cred = keychainStore.Get(...); }
catch (InteropException ex)
{ log.Warn($"Keychain error {ex.ErrorCode}; falling back to cache store"); cred = cacheStore.Get(...); } Prevention
- In CI/headless macOS, create and unlock a dedicated keychain before running git.
- Configure credential.credentialStore explicitly instead of relying on defaults.
- Log the raw error code from InteropException to map unmapped errSec statuses.
- Keep the keychain from auto-locking during long operations.
When it happens
Trigger: Any Security.framework call (SecItemAdd, SecItemCopyMatching, SecItemDelete, etc.) returning an errSec status code not handled by the switch in ThrowIfError — e.g. errSecMissingEntitlement, errSecNotAvailable, or other unmapped statuses.
Common situations: Running on locked-down CI with no keychain access (errSecMissingEntitlement surfacing as unknown); keychain locked or unavailable in headless/SSH sessions; corrupt keychain; unusual macOS versions returning newer status codes.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11).
Data as JSON: /api/errors/68e737bb3bd51892.
Report an issue: GitHub.
Appendix: source
Thrown at src/Core/Interop/MacOS/Native/SecurityFramework.cs:158
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,
}
[StructLayout(LayoutKind.Sequential)]
public struct SecKeychainAttributeInfo
{
public uint Count;
public IntPtr Tag; // uint* (SecKeychainAttrType*)View on GitHub (pinned to e8ce762cd0)