kriasoft/react-starter-kit · error · Error
Invalid email address: ${email}
Error message
Invalid email address: ${email} What it means
sendEmail() validates every recipient with the Zod schema z.email() before touching the Resend client. If any address in options.to (string or array) fails safeParse, it throws this plain Error with the offending address interpolated. It is a pre-flight guard so malformed recipients never reach the provider API.
Source
Thrown at apps/api/lib/email.ts:39
type EmailEnv = Pick<Env, "RESEND_API_KEY" | "RESEND_EMAIL_FROM">;
type TemplateEnv = EmailEnv & Pick<Env, "APP_NAME" | "APP_ORIGIN">;
/**
* Send an email using the Resend client.
*
* @param env Environment variables containing Resend configuration
* @param options Email configuration
*/
export async function sendEmail(env: EmailEnv, options: EmailOptions) {
const emailSchema = z.email();
// Validate all recipients before sending
const recipients = Array.isArray(options.to) ? options.to : [options.to];
for (const email of recipients) {
const result = emailSchema.safeParse(email);
if (!result.success) {
throw new Error(`Invalid email address: ${email}`);
}
}
if (!env.RESEND_API_KEY) {
throw new Error("RESEND_API_KEY environment variable is required");
}
if (!env.RESEND_EMAIL_FROM) {
throw new Error("RESEND_EMAIL_FROM environment variable is required");
}
// A fresh client per send: the Workers runtime reuses an isolate across
// requests, and a module-level client would outlive the env it was built from.
const resend = new Resend(env.RESEND_API_KEY);
try {
const result = await resend.emails.send({
from: options.from || env.RESEND_EMAIL_FROM,View on GitHub (pinned to 0aa7603435)
Solutions
- Log the interpolated address in the message and fix the upstream code or data that produced it
- Validate the recipient with z.email().safeParse() (or check it with a regex) before calling any send* function
- Treat 'Jane <jane@x.com>' style headers as invalid: strip to the bare address or use Resend's displayName support on the 'from' field, not 'to'
- Add a NOT NULL / format constraint on the email column in the database to stop bad values at write time
Example fix
// before
await sendOTP(env, { email: userInput.name + '@', otp, type: 'sign-in' });
// after
const parsed = z.email().safeParse(userInput.email);
if (!parsed.success) return { ok: false, reason: 'invalid-email' };
await sendOTP(env, { email: parsed.data, otp, type: 'sign-in' }); Defensive patterns
Strategy: validation
Validate before calling
import { z } from 'zod';
const emailSchema = z.email();
function assertValidRecipient(to: string | string[]) {
const list = Array.isArray(to) ? to : [to];
for (const e of list) {
const r = emailSchema.safeParse(e.trim());
if (!r.success) throw new Error(`Refusing to send: invalid recipient '${e}'`);
}
} Type guard
function isValidEmail(value: unknown): value is string {
return typeof value === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
} Try / catch
try {
await sendVerificationEmail(env, { user, url });
} catch (error) {
if (error instanceof Error && error.message.startsWith('Invalid email address:')) {
// surface a field-level validation error to the user, not a 500
return { ok: false, field: 'email', message: 'Please provide a valid email address' };
}
throw error;
} Prevention
- Validate email at every write boundary (forms, OAuth profile import) with z.email()
- Never store display-name formatted strings ('Name <a@b.com>') in the email column
- Reject empty/whitespace strings early instead of letting them reach sendEmail
- Add DB constraints (NOT NULL + application-level format check) so bad values can't persist
When it happens
Trigger: Calling sendVerificationEmail/sendPasswordReset/sendOTP with a user.email that is empty, missing an @, contains spaces, or any sendEmail call with options.to being '', 'not-an-email', or an array containing such a value.
Common situations: Unverified user-supplied input stored in the database (e.g. legacy rows or OAuth accounts without an email), concatenating form fields incorrectly, or passing a display string like 'Jane <jane@x.com>' instead of a bare address.
Related errors
- Resend API error: ${result.error.message || result.error.nam
- Failed to send email: ${error instanceof Error ? error.messa
AI-assisted analysis of kriasoft/react-starter-kit@0aa7603435 (2026-08-31).
Data as JSON: /api/errors/7e37d0a8d88d7cb2.
Report an issue: GitHub.