I'm developing an api using strapi 3.6 that I develop without docker locally and I run with docker in production.
Locally, an endpoint that returns a 400 will become a 500 in production.
I have been investigating the issue and when I run docker locally, I also get a 500 instead of a 400.
I couldn't find any relevant resources, does someone have any clue why this could happen?
EDIT
The backend is deployed on AWS Elastic Beanstalk.
What I tried:
All above cases gave me a 500 instead of the expected 400, except for the last case that returned a 400 as expected.
The error displayed in the logs are the ones expected. Only the way the error is returned by the api changes.
Here is the code of the middleware that handles errors globally:
module.exports = (strapi) => {
return {
initialize() {
strapi.app.use(async (ctx, next) => {
try {
await next();
} catch (e) {
strapi.log.error(e, e.stack);
// The error raised is a BusinessError
// Logs are the ones expected
if (e instanceof BusinessError) {
ctx.status = 400;
ctx.body = {
message: e.message,
code: e.code,
};
} else {
throw e;
}
}
});
},
};
};
EDIT 2
local logs:
[
{
"level": 50,
"time": 1641722347605,
"pid": 3986,
"hostname": "MacBook-Pro-de-Baptiste-2.local",
"status": 400,
"headers": {},
"body": {
"code": "ValidationError",
"message": "Validation error(s) present. See embedded errors list for more details.",
"_embedded": {
"errors": [{ "code": "Invalid", "message": "Invalid amount. The supplied amount is greater than your transaction limit.", "path": "/amount/value", "_links": {} }]
}
},
"requestId": "eeb84a16-b250-40d2-9a53-901f92843aa1",
"v": 1
},
{
"level": 50,
"time": 1641722347743,
"msg": "BusinessError: User has reached their transfer limit\n at Object.makeTransfer (/Users/baboo/Documents/projects/burrow/burrow-backend/api/dwolla/services/dwolla.js:154:13)\n at async makeTransfer (/Users/baboo/Documents/projects/burrow/burrow-backend/api/payment/controllers/submitOrder.js:83:7)\n at async /Users/baboo/Documents/projects/burrow/burrow-backend/api/payment/controllers/submitOrder.js:121:25",
"pid": 3986,
"hostname": "MacBook-Pro-de-Baptiste-2.local",
"name": "BusinessError",
"code": "USER_TRANSFER_LIMIT",
"requestId": "eeb84a16-b250-40d2-9a53-901f92843aa1",
"v": 1
},
{
"level": 20,
"time": 1641722347744,
"msg": "POST /checkout/submit-order (7616 ms) \u001b[33m400\u001b[39m",
"pid": 3986,
"hostname": "MacBook-Pro-de-Baptiste-2.local",
"requestId": "eeb84a16-b250-40d2-9a53-901f92843aa1",
"v": 1
}
]
Docker logs:
[
{
"level": 50,
"msg": "{\"code\":\"ValidationError\",\"message\":\"Validation error(s) present. See embedded errors list for more details.\",\"_embedded\":{\"errors\":[{\"code\":\"Invalid\",\"message\":\"Invalid amount. The supplied amount is greater than your transaction limit.\",\"path\":\"/amount/value\",\"_links\":{}}]}}",
"pid": 17,
"hostname": "ef76780ba954",
"type": "Error",
"stack": "Error: {\"code\":\"ValidationError\",\"message\":\"Validation error(s) present. See embedded errors list for more details.\",\"_embedded\":{\"errors\":[{\"code\":\"Invalid\",\"message\":\"Invalid amount. The supplied amount is greater than your transaction limit.\",\"path\":\"/amount/value\",\"_links\":{}}]}}\n at errorFrom (/strapi/node_modules/dwolla-v2/src/dwolla/Token.js:49:15)\n at /strapi/node_modules/dwolla-v2/src/dwolla/Token.js:70:29\n at tryCatcher (/strapi/node_modules/bluebird/js/release/util.js:16:23)\n at Promise._settlePromiseFromHandler (/strapi/node_modules/bluebird/js/release/promise.js:547:31)\n at Promise._settlePromise (/strapi/node_modules/bluebird/js/release/promise.js:604:18)\n at Promise._settlePromise0 (/strapi/node_modules/bluebird/js/release/promise.js:649:10)\n at Promise._settlePromises (/strapi/node_modules/bluebird/js/release/promise.js:729:18)\n at _drainQueueStep (/strapi/node_modules/bluebird/js/release/async.js:93:12)\n at _drainQueue (/strapi/node_modules/bluebird/js/release/async.js:86:9)\n at Async._drainQueues (/strapi/node_modules/bluebird/js/release/async.js:102:5)\n at Immediate.Async.drainQueues [as _onImmediate] (/strapi/node_modules/bluebird/js/release/async.js:15:14)\n at processImmediate (internal/timers.js:464:21)",
"status": 400,
"headers": {},
"body": {
"code": "ValidationError",
"message": "Validation error(s) present. See embedded errors list for more details.",
"_embedded": {
"errors": [{ "code": "Invalid", "message": "Invalid amount. The supplied amount is greater than your transaction limit.", "path": "/amount/value", "_links": {} }]
}
},
"v": 1
},
{
"level": 50,
"msg": "User has reached their transfer limit",
"pid": 17,
"hostname": "ef76780ba954",
"type": "Error",
"stack": "BusinessError: User has reached their transfer limit\n at Object.makeTransfer (/strapi/api/dwolla/services/dwolla.js:154:13)\n at async makeTransfer (/strapi/api/payment/controllers/submitOrder.js:83:7)\n at async /strapi/api/payment/controllers/submitOrder.js:121:25",
"name": "BusinessError",
"code": "USER_TRANSFER_LIMIT",
"isBoom": true,
"isServer": true,
"data": null,
"output": { "statusCode": 500, "payload": { "statusCode": 500, "error": "Internal Server Error", "message": "An internal server error occurred" }, "headers": {} },
"v": 1
},
{
"level": 20,
"msg": "POST /checkout/submit-order (3390 ms) 500",
"pid": 17,
"hostname": "ef76780ba954",
"v": 1
}
]
Looking at the logs, I saw that in production I had this line returned by the api:
...
"isBoom": true,
...
This means that the error is handled by the global error handler boom
that comes with strapi by default.
But we created our own global error handler.
Having a deeper look at the logs, I also saw that the property requestId
was missing in production, a piece of information we also add in one of our custom middleware.
I deduced that our middlewares were not loaded in production.
And when opening the Dockerfile
, I had the answer to our troubles: we are simply not copying the middlewares
folder when building the image.
It's all good now.
Thanks @OneCricketeer to have pointed me in the right direction 🤜🤛