Reputation: 344
I'm making a function that permits me to upload a picture to imgur in my express API (nodejs), I'm encountering an error when calling a function returning a promise:
TypeError: res.status is not a function
at uploadpicture.then
This is my code: Where error is raised:
router.post('/upload', (req, res, next)=> {
var busboy = new Busboy({headers: req.headers});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
if(fieldname == 'image') {
// the buffer
file.fileRead = [];
file.on('data', function(data) {
// add to the buffer as data comes in
this.fileRead.push(data);
});
file.on('end', function() {
// create a new stream with our buffered data
var finalBuffer = Buffer.concat(this.fileRead);
upload = uploadpicture(finalBuffer).then((res)=>{ //success request
console.log(res);
res.status(200).json({success: true, message: "Successfully uploaded !", url: res.data.link});
},(err)=>{ //error
res.status(500).json({success: false, message: "Error happenned while uploading !"});
}).catch((error)=>{
console.log(error);
res.status(500).json({success: false, message: "Error happenned while uploading !"});
});
})
}
});
busboy.on('finish', function() {
//busboy finished
});
req.pipe(busboy);
});
And the function :
function uploadpicture(stream){ //get picture stream
return new Promise((resolve, reject)=>{
var options = {
uri: 'https://api.imgur.com/3/image',
method: 'POST',
headers: {
//'Authorization': 'Client-ID ' + config.client_id_imgur // put client id here
},
formData: {
image: stream,
type: 'file'
},
auth: {
bearer: config.access_token_imgur,
}
};
request(options)
.then((parsedBody)=> {
resolve(parsedBody);
})
.catch((err)=> {
console.log(err);
reject(err.toString())
});
});
}
The code works perfectly, but I don't know why suddenly this error happened, I tried to:
change arrow functions to function(){}
Add next to the route parameters
Nothing worked.
Upvotes: 30
Views: 101395
Reputation: 1
Here's the thing:
the order of (req,res,next) really matters.
In my case the problem was just the order. For example if I want to get user info:
export const getUserInfo = async(res:Response,req:Request,next:NextFunction) => {
try {
const userId = await req.user
const user = await userModel.findById(userId);
res.status(200).json({
success: true,
user,
})
} catch (error:any) {
return next(new ErrorHandler(error.message,400))
}
here I used:
Which was the problem. after switching them on function parameters everything works fine.
Upvotes: 0
Reputation: 5085
Root cause is
Error-handling middleware always takes four arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the next object, you must specify it to maintain the signature. Otherwise, the next object will be interpreted as regular middleware and will fail to handle errors.
In my case, I had enabled ES-Lint and it warned me about unused next
so I removed it... Later on in the production logs started seeing this error. so do not forget to add this to lint ignore list.
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
})
Upvotes: 1
Reputation: 81
You are getting this error:
TypeError: res.status is not a function
Because the order should be (err, req, res, next)
not (req, res, err, next)
,
example below
const errorHandler = (err, req, res, next) => {
const statusCode = res.statusCode === 200 ? 500 : res.statusCode;
res.status(statusCode)
res.json({
message : err.message,
stack :process.env.NODE_ENV === 'production' ? null : err.stack,
})
}
Upvotes: 8
Reputation: 2703
I was setting the type of req
and res
to Request
and Response
, respectively, without actually importing these types from Express!
Upvotes: -1
Reputation: 37
I had the same issue. I resolved it by change the order of functions (req,next,res) to (req,res,next). May it needs them in a strict order to call them properly!
Upvotes: 0
Reputation: 1
If you are using the async/await method:
const notifications = await notifications.aggregate({...})
if(notifications){
return res.status(200).json({ data: notifications })
}else{
return res.status(404).json({ message: 'No notifications found'})
}
Make sure that you are including your return statements. Not including a return statement will cause this. Something else that I was doing is I had JSON
instead of json
, which will most definitely throw an error.
Upvotes: 0
Reputation: 295
Order of parameters really matters i had error in below code
const getImagesByBrand = async (res) => {
try {
const images = await Image.find();
res.status(200).json(images);
} catch (error) {
res.status(500).json(error);
}
};
I was not giving req as parameter and that was the reason for error i just add req,res and it worked
Upvotes: -2
Reputation:
The accepted answer directly addresses the OP's problem, but I post another solution since you can also encounter this error in other places.
When you have:
api.use((error: ErrorRequestHandler, request: ExpressRequest, response: ExpressResponse) => {
response.status(500).end() // response.status is not a function
})
Because the error handling route must accept 4 arguments for express to identify it as an error middleware.
api.use((error: ErrorRequestHandler, request: ExpressRequest, response: ExpressResponse, next: NextFunction) => {
response.status(500).end()
})
Just adding the next function (or whatever argument you're missing) will fix it.
https://github.com/visionmedia/supertest/issues/416#issuecomment-514508137
Upvotes: 47
Reputation: 1499
At this point:
upload = uploadpicture(finalBuffer).then((res)=>{ //success request
the res
is the result of promise uploadpicture
function (that is the parsedBody
), not the res
from the express route. So indeed, it has no status
function. Try change the then
callback name like:
upload = uploadpicture(finalBuffer).then((otherName)=>{ //success request
Upvotes: 20