jaredhanson/passport · error · Error
req#login requires a callback function
Error message
req#login requires a callback function
What it means
Request#login() (aliased as req.logIn) persists the user in the session via the session manager, which requires a completion callback. When a session manager is configured and the session option is enabled (the default), Passport throws this error if the 'done' argument is not a function.
Source
Thrown at lib/http/request.js:36
* @param {User} user
* @param {Object} options
* @param {Function} done
* @api public
*/
req.login =
req.logIn = function(user, options, done) {
if (typeof options == 'function') {
done = options;
options = {};
}
options = options || {};
var property = this._userProperty || 'user';
var session = (options.session === undefined) ? true : options.session;
this[property] = user;
if (session && this._sessionManager) {
if (typeof done != 'function') { throw new Error('req#login requires a callback function'); }
var self = this;
this._sessionManager.logIn(this, user, options, function(err) {
if (err) { self[property] = null; return done(err); }
done();
});
} else {
done && done();
}
};
/**
* Terminate an existing login session.
*
* @api public
*/
req.logout =
req.logOut = function(options, done) {View on GitHub (pinned to 217018dbc4)
Solutions
- Add a callback: req.logIn(user, function(err) { ... })
- If passing options, put the callback last: req.logIn(user, {session: true}, cb)
- Pass {session: false} if you don't need session persistence, which skips the callback requirement
- Check argument order — an options object passed where the callback belongs triggers the throw
Example fix
// before
req.logIn(user);
res.redirect('/');
// after
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/');
}); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof callback !== 'function') {
throw new TypeError('req.logIn requires a callback function argument');
} Type guard
function isFn(x) { return typeof x === 'function'; }
// usage: if (!isFn(cb)) { /* provide default or fix call site */ } Try / catch
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user) {
if (err) { return next(err); }
try {
req.logIn(user, function(err) {
if (err) { return next(err); }
res.redirect('/');
});
} catch (e) { next(e); }
})(req, res, next);
}); Prevention
- Always supply a callback as the last argument to req.logIn
- Use req.logIn(user, {session: false}, cb) only when you intentionally skip session persistence
- Lint for req.logIn( calls with a single argument
- After login failure inside the callback, clear the user and return the error to next()
When it happens
Trigger: calling req.logIn(user) with no second argument, or passing a non-function (e.g. an options object as second arg, or options in the wrong position) while session persistence is on.
Common situations: Copying older tutorials where req.logIn(user) without a callback appeared to work in code paths without a session manager; forgetting the callback inside a custom login route; passing options but forgetting the trailing callback.
Related errors
AI-assisted analysis of jaredhanson/passport@217018dbc4 (2026-08-31).
Data as JSON: /api/errors/210e28db237011f8.
Report an issue: GitHub.