{"record":{"id":"d88f820cd7a31205","repo":"gravitational/teleport","slug":"no-credentials-for-user-q","errorCode":null,"errorMessage":"no credentials for user %q","messagePattern":"no credentials for user %q","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/auth/webauthncli/fido2.go","lineNumber":420,"sourceCode":"\tcase l == 0:\n\t\treturn nil, errors.New(\"authenticator returned empty assertions\")\n\n\t// MFA or single account.\n\t// Note that authenticators don't return the user name, display name or icon\n\t// for a single account per RP.\n\t// See the authenticatorGetAssertion response, user member (0x04):\n\t// https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#authenticatorgetassertion-response-structure\n\tcase !passwordless, l == 1:\n\t\treturn assertions[0], nil\n\n\t// Explicit user required. First occurrence wins.\n\tcase user != \"\":\n\t\tfor _, assertion := range assertions {\n\t\t\tif assertion.User.Name == user {\n\t\t\t\treturn assertion, nil\n\t\t\t}\n\t\t}\n\t\treturn nil, fmt.Errorf(\"no credentials for user %q\", user)\n\t}\n\n\t// Prepare credentials and show picker.\n\tcreds := make([]*CredentialInfo, len(assertions))\n\tcredToAssertion := make(map[*CredentialInfo]*libfido2.Assertion)\n\tfor i, assertion := range assertions {\n\t\tcred := &CredentialInfo{\n\t\t\tID: assertion.CredentialID,\n\t\t\tUser: UserInfo{\n\t\t\t\tUserHandle: assertion.User.ID,\n\t\t\t\tName:       assertion.User.Name,\n\t\t\t},\n\t\t}\n\t\tcredToAssertion[cred] = assertion\n\t\tcreds[i] = cred\n\t}\n\tchosen, err := prompt.PromptCredential(creds)\n\tif err != nil {","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/auth/webauthncli/fido2.go#L402-L438","documentation":"pickAssertion in the FIDO2 login flow selects which returned assertion to use. When a target username was supplied (user != \"\") and none of the assertions returned by the security key carry a matching assertion.User.Name, the flow fails with this error rather than guessing. It means the key authenticated but has no credential bound to that specific user account.","triggerScenarios":"Calling login with a specific username against a FIDO2 device that holds credentials for other users (or for which resident credentials for that user do not exist), so all returned assertions have User.Name != user.","commonSituations":"Typos or different casing in the username; the user's credential was registered on a different security key; the key was registered with an empty/different username (e.g. registered non-discoverable or under another account); after re-imaging or resetting a key that lost resident credentials.","solutions":["Verify the username passed to the login flow exactly matches the one used at registration (case-sensitive).","List credentials on the device (or let the user pick without a name filter) to see which users the key actually holds.","Register the user on the current security key with fido2Register before attempting login.","If the credential was registered with an empty username, call login with an empty user to trigger the credential picker instead of name matching."],"exampleFix":"// before\nassertion, err := fido2Login(ctx, cfg, user=\"Alice\", ...) // key has \"alice\"\n// after — match exactly or fall back to picker\nif !hasAssertionForUser(assertions, user) {\n    user = \"\" // empty user => interactive credential picker\n}\nassertion, err := fido2Login(ctx, cfg, user, ...)","handlingStrategy":"validation","validationCode":"creds, err := fido2.ListCredentials(...)\nif err != nil { return err }\nhasUser := false\nfor _, c := range creds {\n    if c.User == user { hasUser = true; break }\n}\nif !hasUser {\n    return fmt.Errorf(\"user %q is not registered on this security key\", user)\n}","typeGuard":"func keyHasUser(assertions []*libfido2.Assertion, user string) bool {\n    for _, a := range assertions {\n        if a.User != nil && a.User.Name == user { return true }\n    }\n    return false\n}","tryCatchPattern":"assertion, err := pickAssertion(ctx, cfg, assertions, user, prompt)\nif err != nil {\n    if strings.Contains(err.Error(), \"no credentials for user\") {\n        // retry without name filter so the interactive picker runs\n        return pickAssertion(ctx, cfg, assertions, \"\", prompt)\n    }\n    return trace.Wrap(err)\n}","preventionTips":["Confirm the username matches registration exactly (case-sensitive) before login.","Register the user on the security key being used.","Pass an empty user to fall back to the interactive credential picker when unsure which key holds the account."],"tags":["webauthn","fido2","hardware-keys"],"backgroundTag":"no-credential-for-user","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}