{"record":{"id":"210e28db237011f8","repo":"jaredhanson/passport","slug":"req-login-requires-a-callback-function","errorCode":null,"errorMessage":"req#login requires a callback function","messagePattern":"req#login requires a callback function","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/http/request.js","lineNumber":36,"sourceCode":" * @param {User} user\n * @param {Object} options\n * @param {Function} done\n * @api public\n */\nreq.login =\nreq.logIn = function(user, options, done) {\n  if (typeof options == 'function') {\n    done = options;\n    options = {};\n  }\n  options = options || {};\n  \n  var property = this._userProperty || 'user';\n  var session = (options.session === undefined) ? true : options.session;\n  \n  this[property] = user;\n  if (session && this._sessionManager) {\n    if (typeof done != 'function') { throw new Error('req#login requires a callback function'); }\n    \n    var self = this;\n    this._sessionManager.logIn(this, user, options, function(err) {\n      if (err) { self[property] = null; return done(err); }\n      done();\n    });\n  } else {\n    done && done();\n  }\n};\n\n/**\n * Terminate an existing login session.\n *\n * @api public\n */\nreq.logout =\nreq.logOut = function(options, done) {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/jaredhanson/passport/blob/217018dbc46dcd4118dd6f2c60c8d97010c587f8/lib/http/request.js#L18-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nreq.logIn(user);\nres.redirect('/');\n// after\nreq.logIn(user, function(err) {\n  if (err) { return next(err); }\n  return res.redirect('/');\n});","handlingStrategy":"type-guard","validationCode":"if (typeof callback !== 'function') {\n  throw new TypeError('req.logIn requires a callback function argument');\n}","typeGuard":"function isFn(x) { return typeof x === 'function'; }\n// usage: if (!isFn(cb)) { /* provide default or fix call site */ }","tryCatchPattern":"app.post('/login', function(req, res, next) {\n  passport.authenticate('local', function(err, user) {\n    if (err) { return next(err); }\n    try {\n      req.logIn(user, function(err) {\n        if (err) { return next(err); }\n        res.redirect('/');\n      });\n    } catch (e) { next(e); }\n  })(req, res, next);\n});","preventionTips":["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()"],"tags":["passport","callback-required","session"],"backgroundTag":"missing-callback-argument","analyzedSha":"217018dbc46dcd4118dd6f2c60c8d97010c587f8","analyzedAt":"2026-08-31T21:59:48.726Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}