如何解决Passport插件用户注册时陷入死循环的问题?
Let’s break down what’s likely causing this issue and how to fix it step by step:
1. Missing Response on Successful Login
Looking at your code snippet, the biggest red flag is that you don’t send any response when req.logIn succeeds. When a request hits your server and never gets a response, the browser will eventually time out and retry the request—creating that loop of repeated calls you’re seeing.
Here’s the problematic section:
req.logIn(user, function (err) { if (err) { // Error handling here (has responses) console.log("req.logIn err ==", err); if (isJSON) return res.json({ status: false }) req.flash( "error", "Something Went Wrong: Please try again later." ); if (isJSON) return res.json({ status: false }) return res.redirect("back"); } // NO RESPONSE SENT HERE WHEN THERE'S NO ERROR! })
Fix: Add a Success Response
You need to send a clear response once the user is successfully logged in. For example:
req.logIn(user, function (err) { if (err) { console.log("req.logIn err ==", err); if (isJSON) return res.json({ status: false }) req.flash( "error", "Something Went Wrong: Please try again later." ); return res.redirect("back"); } // Send success response here if (isJSON) { return res.json({ status: true, user: user }); } req.flash("success", "Registration successful!"); return res.redirect("/dashboard"); // Replace with your desired success route })
2. Check Your local-signup Strategy Implementation
The async_hooks.js hang suggests there might be an issue with how you’re handling the done callback in your Passport strategy. If you don’t call done() correctly (or at all) in your strategy, it can leave asynchronous hooks in a stuck state, leading to hangs.
Make sure your strategy follows this pattern:
passport.use('local-signup', new LocalStrategy({ usernameField: 'email', // Adjust to match your form's username field passwordField: 'password', passReqToCallback: true // Enable if you need access to the request object }, function(req, email, password, done) { // Check if user already exists User.findOne({ 'local.email': email }, function(err, user) { if (err) return done(err); // Pass errors to the done callback immediately if (user) { // User exists, return error message return done(null, false, { message: 'This email is already registered' }); } else { // Create new user const newUser = new User(); newUser.local.email = email; newUser.local.password = newUser.generateHash(password); // Use your password hashing method newUser.save(function(err) { if (err) throw err; return done(null, newUser); // Pass the new user to complete the auth flow }); } }); }));
Key checks here:
- Always call
done()—whether there’s an error, the user exists (so signup fails), or the new user is created successfully. - When there’s no error but you need to reject the signup (e.g., existing user), pass
nullas the first argument todone(), followed byfalseand an info object.
3. Verify Middleware Order
Ensure your Express middleware is ordered correctly—wrong order can break Passport’s functionality:
express.urlencoded()orexpress.json()(to parse request bodies)express.session()(if using session-based authentication)passport.initialize()passport.session()(only if using sessions)- Your route handlers (including the signup route)
4. Debug Async Hook Issues
If the problem persists after fixing the above, enable Node.js async hook debugging to get more context:
NODE_DEBUG=async_hooks node your-app.js
This will log detailed info about async hook events, which can help pinpoint exactly which async operation is causing the emitDestroyNative hang.
内容的提问来源于stack exchange,提问作者Tushar_noob

