{"record":{"id":"674c10803ef9958a","repo":"kataras/iris","slug":"auth-signin-w","errorCode":null,"errorMessage":"auth: signin: %w","messagePattern":"auth: signin: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/auth.go","lineNumber":234,"sourceCode":"}\n\n// Signin signs a token based on the provided username and password\n// and returns a pair of access and refresh tokens.\n//\n// Signin calls the Provider.Signin method to check if a user\n// is authenticated by the given username and password combination.\nfunc (s *Auth[T]) Signin(ctx stdContext.Context, username, password string) ([]byte, []byte, error) {\n\tvar t T\n\n\t// get \"t\" from a valid provider.\n\tif n := len(s.providers); n > 0 {\n\t\tfor i := 0; i < n; i++ {\n\t\t\tp := s.providers[i]\n\n\t\t\tv, err := p.Signin(ctx, username, password)\n\t\t\tif err != nil {\n\t\t\t\tif i == n-1 { // last provider errored.\n\t\t\t\t\treturn nil, nil, fmt.Errorf(\"auth: signin: %w\", err)\n\t\t\t\t}\n\t\t\t\t// keep searching.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// found.\n\t\t\tt = v\n\t\t\tbreak\n\t\t}\n\t} else {\n\t\treturn nil, nil, fmt.Errorf(\"auth: signin: no provider\")\n\t}\n\n\t// sign the tokens.\n\taccessToken, refreshToken, err := s.sign(t)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"auth: signin: %w\", err)\n\t}","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/auth/auth.go#L216-L252","documentation":"Auth.Signin returns 'auth: signin: %w' wrapping the underlying error only when the LAST registered provider fails. Earlier providers are skipped silently ('keep searching'); if the final provider also errors, its error is wrapped and propagated. The %w wrap means callers can inspect the provider error with errors.Is/As.","triggerScenarios":"Calling auth.Signin (or the SigninHandler endpoint) with credentials that fail against every provider, and the last provider returns an error such as invalid credentials or an internal provider failure.","commonSituations":"Wrong username/password on the last-configured provider (e.g. a local DB provider after a broken LDAP one); a provider's backing store being down; provider misconfiguration (bad DSN, wrong user table).","solutions":["Inspect the wrapped cause with errors.Is/As or %v on the error to see the last provider's failure reason","Fix the last provider's configuration or backing store","Reorder providers so the most reliable one is last (or handles the common case first)","Log each provider's attempt to identify which one ultimately failed"],"exampleFix":"// before\n_, _, err := a.Signin(ctx, username, password)\nreturn err\n// after\n_, _, err := a.Signin(ctx, username, password)\nif err != nil {\n    log.Printf(\"signin failed: %v\", err) // shows last provider cause\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// pre-validate credentials shape before hitting providers\nif username == \"\" || password == \"\" { return errors.New(\"missing credentials\") }","typeGuard":"func isSigninProviderErr(err error) bool { return err != nil && strings.HasPrefix(err.Error(), \"auth: signin: \") && !strings.Contains(err.Error(), \"no provider\") }","tryCatchPattern":"_, _, err := a.Signin(ctx, user, pass)\nif err != nil {\n    var target error\n    if errors.As(err, &target) || errors.Unwrap(err) != nil {\n        log.Printf(\"last provider failed: %v\", errors.Unwrap(err))\n    }\n    http.Error(w, \"invalid credentials\", http.StatusUnauthorized)\n}","preventionTips":["Log the unwrapped cause to identify the failing provider","Register the most reliable provider last","Health-check provider backends at startup","Return uniform 'invalid credentials' to clients, details to logs"],"tags":["auth","signin","providers"],"backgroundTag":"authentication-failed","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}