git-ecosystem/git-credential-manager · error · InteropException

ErrorSecInvalidKeychain

ErrorSecInvalidKeychain

Error message

The keychain is not valid.

What it means

Thrown by SecurityFramework.ThrowIfError when a Security.framework call returns errSecInvalidKeychain (-25295): the keychain reference or path is not a valid keychain. Unlike -25294 (keychain absent), this means the keychain object exists but is malformed, corrupted, wrong format, or unusable by the Security framework. The library converts the OS status into a descriptive InteropException.

Solutions

  1. Repair the keychain: open Keychain Access and run Keychain First Aid, or `security verify-keychain` / recreate the keychain and re-import items
  2. Confirm the default keychain is the correct file: `security default-keychain` and point it back to ~/Library/Keychains/login.keychain-db
  3. Restore the keychain from Time Machine backup or re-create it (`security create-keychain`) and let apps re-store credentials
  4. Log out/in after recreating the keychain so the securityd session picks up the new default keychain

Example fix

// before
# keychain corrupted -> errSecInvalidKeychain
security default-keychain ~/Library/Keychains/old-broken.keychain
// after
security create-keychain -p "" ~/Library/Keychains/login.keychain-db
security default-keychain ~/Library/Keychains/login.keychain-db
security unlock-keychain ~/Library/Keychains/login.keychain-db
Defensive patterns

Strategy: try-catch

Validate before calling

using System;
using System.Diagnostics;

static bool KeychainIsValid(string keychainPath)
{
    var psi = new ProcessStartInfo("security", $"verify-keychain {keychainPath}")
    {
        UseShellExecute = false
    };
    using var p = Process.Start(psi);
    p.WaitForExit();
    return p.ExitCode == 0;
}

if (!KeychainIsValid("~/Library/Keychains/login.keychain-db"))
{
    // repair/recreate the keychain before performing keychain operations
}

Try / catch

try
{
    keychain.Get(service, account);
}
catch (InteropException ex) when (ex.ErrorCode == -25295) // errSecInvalidKeychain
{
    // Keychain corrupt/invalid: repair or recreate, then retry or fall back
}

Prevention

When it happens

Trigger: Any MacOSKeychain operation whose underlying SecKeychain* call fails with OS status -25295 and is passed to ThrowIfError — e.g. finding, adding, updating, or deleting generic passwords against a keychain that the framework considers invalid.

Common situations: Corrupted login.keychain-db after disk issues or interrupted writes, keychain files created/copied from another macOS version or user, a path pointing to a non-keychain file, or older keychain formats after macOS upgrades.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11). Data as JSON: /api/errors/6c3a04182a0da5bf. Report an issue: GitHub.

Appendix: source

Thrown at src/Core/Interop/MacOS/Native/SecurityFramework.cs:144

        public const int ErrorSecNoSuchKeychain = -25294;
        public const int ErrorSecInvalidKeychain = -25295;
        public const int ErrorSecAuthFailed = -25293;
        public const int ErrorSecDuplicateItem = -25299;
        public const int ErrorSecItemNotFound = -25300;
        public const int ErrorSecInteractionNotAllowed = -25308;
        public const int ErrorSecInteractionRequired = -25315;
        public const int ErrorSecNoSuchAttr = -25303;

        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);
            }
        }
    }

View on GitHub (pinned to e8ce762cd0)