Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialKristian Woods
23,414 PointsWhy am I getting the error: "Can't set headers after they are sent." - in my node application?
I have a pretty basic node application, which I'm using to create a REST API. I'm getting a very strange error when I try to make a post
request to the API: http://localhost:5000/login
ERROR: "Can't set headers after they are sent"
I have broken it up in to the three files that are required to set up the API: 1) The server file that listens on the port 2) The route file 3) The controller file, that handles the req, res 4) AppError - my custom class that handles errors
without else clause - (gets error):
What is happening- if the password and email are empty, then it should throw an error, and end the program, alongside send the appropriate error message. However, what is actually happening is, that I'm getting the "success". So it's skipping the conditional. Why is that?
exports.login = (req, res, next) => {
const {email, password} = req.body;
//if password and email are empty, then create an error
if(!email || !password) {
next(new AppError('Please provide email and password', 400));
}
const token = 'login successful';
res.status(201).json({
status: 'success',
token: token
});
};
with else clause - (no error)
This version works, as I use the "else" clause
exports.login = (req, res, next) => {
const {email, password} = req.body;
if(!email || !password) {
next(new AppError('Please provide email and password', 400));
} else {
const token = 'login successful';
res.status(201).json({
status: 'success',
token: token
});
}
};
SERVER.JS FILE:
// import routes
const productsRoute = require('./routes/products');
const userRoute = require('./routes/userRoute');
app.use('/products', productsRoute);
app.use('/', userRoute);
// will catch all urls that arent recognised
app.all('*', (req, res, next) => {
next(new AppError(`Can't find ${req.originalUrl} on the server!`, 404));
});
// global error handler: express will know that if there are 4 params, that it is an error middleware
app.use(globalErrorHandler);
const PORT = 5000;
app.listen(PORT, () => console.log(`server started on port ${PORT}`));
ROUTE FILE: (userRoute)
const express = require('express');
const router = express.Router();
const authControllers = require('../controllers/authController');
router.post('/signup', authControllers.signup);
router.post('/login', authControllers.login);
module.exports = router;
CONTROLLER FILE:
exports.login = (req, res, next) => {
const {email, password} = req.body;
if(!email || !password) {
next(new AppError('Please provide email and password', 400));
}
const token = 'login successful';
res.status(201).json({
status: 'success',
token: token
});
};
APP ERROR FILE
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
this.isOperational = true;
Error.captureStackTrace(this, this.constructor)
}
}
module.exports = AppError;
1 Answer
Kristian Woods
23,414 PointsI figured it out - I just needed to include a return before the next() function
if(!email || !password) {
return next(new AppError('Please provide email and password', 400));
}