Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why doesn't this code throw an error? #1004

Open
gc opened this issue Mar 5, 2024 · 3 comments
Open

Why doesn't this code throw an error? #1004

gc opened this issue Mar 5, 2024 · 3 comments

Comments

@gc
Copy link

gc commented Mar 5, 2024

I've spent some time debugging my code to find an issue, and realized its the result of fastify swallowing any exceptions thrown after the reply is sent. My use case is I check all responses my routes send, against a strict schema. Is there a reason it's like this, or is it a bug in fastify? I'm aware fastify does log an error, but that doesn't help me handle/see the error.

Fastify Version: 4.26.2

Minimal reproduction

const myAbstractedRoutes = [{
    name: "route",
    path: "/test",
    run: (req, res) => res.send("Hello World")
}];

const fastify = require('fastify')({
  logger: true
})

fastify.setErrorHandler((error, _request, reply) => {
	console.log("This really should log!");
	reply.send("Error");
});


for (const route of myAbstractedRoutes) {
    fastify.get(route.path, async (req, res) => {
        // Uncomment to test this error is logged
        // throw new Error("Pre Run Test Error");
        await route.run(req, res);
        // This error is swallowed.
        throw new Error("Post Run Test Error");
    });
}

fastify.listen({ port: 3000 });
@climba03003
Copy link
Member

climba03003 commented Mar 5, 2024

For me it is a desire behavior. The reason is that every hooks or handler in fastify provides you to reply to the client.
If any error is able to go through the hooks after reply, there will be a bunch of log and unexpected error telling you that you sent twice to the client or meeting a race condition.

@KerwinChina
Copy link

Fastify's default behavior is designed to swallow errors thrown after the response has been sent to prevent unhandled promise rejections or errors from crashing the Node.js process. your code can use Fastify hooks, specifically the onSend hook.
const myAbstractedRoutes = [{
name: "route",
path: "/test",
run: async (req, res) => res.send("Hello World")
}];

const fastify = require('fastify')({
logger: true
});

fastify.addHook('onSend', async (request, reply, payload) => {
// Check payload against your strict schema here
try {
// Example: Ensure payload is a string
if (typeof payload !== 'string') {
throw new Error('Invalid response payload');
}
} catch (error) {
// Handle the validation error here
console.error('Response validation error:', error.message);
reply.code(500).send('Internal Server Error');
}
});

for (const route of myAbstractedRoutes) {
fastify.get(route.path, async (req, res) => {
// Uncomment to test this error is logged
// throw new Error("Pre Run Test Error");
await route.run(req, res);
// This error is caught by the onSend hook
throw new Error("Post Run Test Error");
});
}

fastify.listen({ port: 3000 });

@melroy89
Copy link
Contributor

@KerwinChina Add your code between code blocks in markdown. This is not readable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants