I’m trying to use Better Auth in a Fastify application
Below is the part of my configuration:
const betterAuthOptions: BetterAuthOptions = {
// Better Auth should delegate its logs to Fastify
logger: {
disabled: false,
level: server.log.level as 'info',
log(level, message, ...args) {
// Forward everything to Fastify’s pino instance
server.log[level]({ ...args }, message);
},
},
plugins: [
emailOTP({
async sendVerificationOTP({ email, otp, type }) {
server.log.debug({ email, otp, type }, 'emailOTP');
// ➜ This call is where the error occurs
if (type === 'sign-in') {
await emailer.sendOTP({ email, otp });
}
},
generateOTP: genOtp,
disableSignUp: false,
expiresIn: 300, // 5 minutes
sendVerificationOnSignUp: false,
}),
],
};
Problem
When emailer.sendOTP throws the error:
Isn’t caught by the Better Auth logger I configured above.
Doesn’t appear in Fastify’s setErrorHandler.
Instead shows up only as an unhandled error in the console.
What I expected
Because sendVerificationOTP lives inside the Better Auth plugin, I assumed any exceptions thrown there would bubble up to Better Auth’s internal error-handling path and be logged by the custom logger I passed in.
What actually happens
SERVER_ERROR: TypeError: fetch failed
at node:internal/deps/undici/undici:13392:13
Fastify’s structured logs (Pino)
Better Auth’s logger callback above
Questions
Is this the intended behaviour, i.e. does Better Auth expect you to wrap sendVerificationOTP in a try/catch?
If not, is there a recommended pattern for ensuring errors inside plugin callbacks are routed through Better Auth’s logger (or Fastify’s error handler)?
Has anyone run into this and found a workaround other than manually wrapping emailer.sendOTP in a try/catch and logging it yourself?
Any guidance or examples would be greatly appreciated.