{"record":{"id":"a08a9ceb5a0fb3f6","repo":"git-ecosystem/git-credential-manager","slug":"errorsecinteractionrequired","errorCode":"ErrorSecInteractionRequired","errorMessage":"User interaction is required.","messagePattern":"User interaction is required\\.","errorType":"error_code","errorClass":"InteropException","httpStatus":null,"severity":"error","filePath":"src/Core/Interop/MacOS/Native/SecurityFramework.cs","lineNumber":154,"sourceCode":"        {\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,\n        SessionIsRemote = 0x1000,\n    }\n\n    [StructLayout(LayoutKind.Sequential)]","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/Core/Interop/MacOS/Native/SecurityFramework.cs#L136-L172","documentation":"InteropException thrown by SecurityFramework.ThrowIfError when the macOS Security framework returns errSecInteractionRequired (-25315). It means the operation can only succeed if the user is prompted (e.g. to unlock the keychain, authorize access, or satisfy an authentication context), but the call was made in a way that no prompt was shown. Unlike errSecInteractionNotAllowed, the request itself is valid; a UI round-trip is required to proceed.","triggerScenarios":"SecItemCopyMatching/SecKeychainFindGenericPassword on an item whose ACL or kSecAccessControl policy requires user consent (Touch ID, device passcode, re-authentication) without kSecUseAuthenticationUI set appropriately; first access to a locked keychain item where authorization UI was suppressed; operations needing authorization rights that must be acquired interactively.","commonSituations":"Touch ID / Apple Watch-protected items accessed from a context where the prompt cannot display; apps calling keychain APIs during app startup before a window is available; automated tests hitting items configured with user-presence requirement; access-control items queried with UI explicitly disabled then failing because interaction was actually mandatory.","solutions":["Allow Security Server UI for the call (remove kSecUseAuthenticationUIDisallow; use Allow or Failover so the prompt appears).","Prompt the user deliberately: run the operation from a foreground, UI-capable context after informing the user why the keychain prompt appears.","If user presence is not actually required, recreate the item without kSecAccessControlUserPresence/biometry flags so reads succeed non-interactively.","Retry the operation after the user completes authentication (e.g. re-call after the Touch ID / unlock dialog succeeds).","For background/daemons, use items without user-presence ACL, or cache an unlocked session via SecKeychainUnlock with stored credentials."],"exampleFix":"// before: silent query of a user-presence-protected item throws\nvar query = new SecQueryDictionary(service).AsDictionary();\nerr = SecItemCopyMatching(query, out result);\nSecurityFramework.ThrowIfError(err); // -25315: needs a user prompt\n\n// after: perform the call where UI is allowed and retry once the user authenticates\nquery[kSecUseAuthenticationUI] = kSecUseAuthenticationUIAllow;\nerr = SecItemCopyMatching(query, out result);\nif (err == ErrorSecInteractionRequired)\n{\n    ShowExplainUnlockDialog(); // user completes Touch ID / password prompt\n    err = SecItemCopyMatching(query, out result); // retry\n}\nSecurityFramework.ThrowIfError(err);","handlingStrategy":"retry","validationCode":"// Detect items that require user presence before attempting non-interactive access\nbool requiresUserPresence = query.ContainsKey(kSecAttrAccessControl);\nif (requiresUserPresence && runningHeadless)\n{\n    throw new InvalidOperationException(\"Item requires user interaction; run in a UI session or store the item without kSecAccessControl.\");\n}","typeGuard":"static bool IsSecInteractionRequired(InteropException ex) => ex.ErrorCode == -25315; // errSecInteractionRequired","tryCatchPattern":"try\n{\n    credential = ReadProtectedCredential(query);\n}\ncatch (InteropException ex) when (ex.ErrorCode == -25315)\n{\n    // A user prompt is mandatory: surface the request to the UI layer and retry once.\n    await uiService.ShowAuthenticationPromptAsync();\n    credential = ReadProtectedCredential(query); // single retry after user authenticated\n}","preventionTips":["Don't disable Security UI (kSecUseAuthenticationUIDisallow) unless you know the item never requires consent.","Only set kSecAccessControl user-presence/biometry flags on items that genuinely need them; store service-level tokens without them.","Call keychain APIs from a foreground UI context after startup completes, not from silent background tasks that cannot show prompts.","Always allow exactly one retry after user authentication completes; avoid infinite prompt loops.","For automated environments, provision duplicates of secrets without access-control flags in a separate keychain."],"tags":["macos","keychain","security-framework","user-interaction","touch-id","interop"],"backgroundTag":"authentication-required","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"}