{"record":{"id":"bbcdc324d1cae9d7","repo":"git-ecosystem/git-credential-manager","slug":"errorsecitemnotfound","errorCode":"ErrorSecItemNotFound","errorMessage":"The item cannot be found.","messagePattern":"The item cannot be found\\.","errorType":"error_code","errorClass":"InteropException","httpStatus":null,"severity":"error","filePath":"src/Core/Interop/MacOS/Native/SecurityFramework.cs","lineNumber":150,"sourceCode":"        public const int ErrorSecInteractionRequired = -25315;\n        public const int ErrorSecNoSuchAttr = -25303;\n\n        public static void ThrowIfError(int error, string defaultErrorMessage = \"Unknown error.\")\n        {\n            switch (error)\n            {\n                case OK:\n                    return;\n                case ErrorSecNoSuchKeychain:\n                    throw new InteropException(\"The keychain does not exist.\", error);\n                case ErrorSecInvalidKeychain:\n                    throw new InteropException(\"The keychain is not valid.\", error);\n                case ErrorSecAuthFailed:\n                    throw new InteropException(\"Authorization/Authentication failed.\", error);\n                case ErrorSecDuplicateItem:\n                    throw new InteropException(\"The item already exists.\", error);\n                case ErrorSecItemNotFound:\n                    throw new InteropException(\"The item cannot be found.\", error);\n                case ErrorSecInteractionNotAllowed:\n                    throw new InteropException(\"Interaction with the Security Server is not allowed.\", error);\n                case ErrorSecInteractionRequired:\n                    throw new InteropException(\"User interaction is required.\", error);\n                case ErrorSecNoSuchAttr:\n                    throw new InteropException(\"The attribute does not exist.\", error);\n                default:\n                    throw new InteropException(defaultErrorMessage, error);\n            }\n        }\n    }\n\n    [Flags]\n    public enum SessionAttributeBits\n    {\n        SessionIsRoot = 0x0001,\n        SessionHasGraphicAccess = 0x0010,\n        SessionHasTty = 0x0020,","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/Core/Interop/MacOS/Native/SecurityFramework.cs#L132-L168","documentation":"InteropException thrown by SecurityFramework.ThrowIfError when the macOS Security framework returns errSecItemNotFound (-25300). It means a query (SecItemCopyMatching, SecKeychainFindGenericPassword, SecKeychainItemCopyFromPersistentReference) matched no keychain item for the given service/account/persistent reference. This is the keychain equivalent of 'record not found', not a system failure.","triggerScenarios":"SecKeychainFindGenericPassword with a service/account string that was never stored (or stored under different casing/whitespace); SecItemCopyMatching whose query dictionary matches zero items; SecKeychainItemCopyFromPersistentReference given a stale persistent reference from an item that was deleted or from a different keychain.","commonSituations":"Querying a credential before the code path that stores it ever ran; the item was created in the login keychain but the app now targets a different (custom/Shared) keychain; typos or trimming differences in the service name; the user deleted the item via Keychain Access; restoring a persistent reference after a keychain reset or macOS migration.","solutions":["Verify the item exists (Keychain Access or `security find-generic-password -s <service>`) and that service/account strings match exactly.","Store the item first if missing, or handle not-found as a normal 'no credential yet' case rather than an unexpected failure.","Ensure you are querying the same keychain the item was created in (pass the explicit keychain ref, not null/default).","If using a persistent reference, re-acquire it from a fresh SecKeychainItemCopyFromPersistentReference-capable source; recreate the item and store a new reference if it is stale.","Normalize service/account strings (trim, consistent casing) before both storing and querying."],"exampleFix":"// before: throwing away the not-found case as fatal\nerr = SecKeychainFindGenericPassword(null, serviceLength, service, accountLength, account, out length, out data, IntPtr.Zero);\nSecurityFramework.ThrowIfError(err); // InteropException -25300 when nothing stored yet\n\n// after: treat not-found as 'no credential stored yet'\nerr = SecKeychainFindGenericPassword(null, serviceLength, service, accountLength, account, out length, out data, IntPtr.Zero);\nif (err == ErrorSecItemNotFound)\n{\n    credential = ProvisionNewCredential(); // store it via SecKeychainAddGenericPassword\n}\nelse\n{\n    SecurityFramework.ThrowIfError(err);\n    credential = ReadCredential(data, length);\n}","handlingStrategy":"try-catch","validationCode":"// Probe existence before reading the secret\nint err = SecKeychainFindGenericPassword(null, service.Length, service, account.Length, account, out _, out IntPtr _, out IntPtr _);\nbool credentialStored = err == OK; // -25300 means nothing stored yet under that service/account\nif (!credentialStored) ProvisionCredential();","typeGuard":"static bool IsSecItemNotFound(InteropException ex) => ex.ErrorCode == -25300; // errSecItemNotFound","tryCatchPattern":"try\n{\n    credential = ReadCredentialFromKeychain(service, account);\n}\ncatch (InteropException ex) when (ex.ErrorCode == -25300)\n{\n    // No credential stored yet — normal first-run case.\n    credential = ProvisionAndStoreCredential(service, account);\n}","preventionTips":["Standardize and normalize service/account strings (trim, exact casing) at a single write/read boundary.","Check item existence with Keychain Access or `security find-generic-password -s <service>` when debugging.","Persist keychain persistent references alongside a validity check; refresh them after keychain resets or migrations.","Query the same keychain the item was written to (pass the explicit keychain ref rather than relying on defaults).","Treat not-found as a first-run flow, not a crash: always have a provisioning path."],"tags":["macos","keychain","security-framework","not-found","interop"],"backgroundTag":"record-not-found","analyzedSha":"e8ce762cd04b4100ae637b5fbf39ef9d0a96561e","analyzedAt":"2026-09-11T17:15:08.753Z","contentChangedAt":"2026-09-11T17:15:08.753Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}