toeverything/AFFiNE · warning · InvalidEmail

invalid_email

invalid_email

Error message

An invalid email provided: ${email}

What it means

assertValidEmail runs the input through zod's z.string().email() and throws invalid_email (with the offending value) when the string is not a well-formed address. Auth flows call it before touching the database, so malformed emails never reach user lookup.

Solutions

  1. Send a valid email address in the email field
  2. Mirror the same validation client-side (zod or regex) before submit
  3. Trim whitespace from form inputs before sending

Example fix

// before
await signIn(emailInput, password); // 'user name@host' -> invalid_email

// after
const email = emailInput.trim();
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) throw new Error('enter a valid email');
await signIn(email, password);
Defensive patterns

Strategy: validation

Validate before calling

// client-side pre-check matching the server rule
const email = raw.trim();
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) {
  throw new Error('enter a valid email address');
}

Type guard

function isValidEmail(email: string): boolean {
  return z.string().email().safeParse(email.trim()).success;
}

Try / catch

try {
  await signUp(email, password);
} catch (e) {
  if (e?.extensions?.code === 'INVALID_EMAIL') markEmailFieldInvalid();
  else throw e;
}

Prevention

When it happens

Trigger: Sign-up/sign-in/email-change with a malformed address (missing @, spaces, bare username); sending a username or display name in the email field; untrimmed whitespace-padded input.

Common situations: Forms without client-side validation; password managers filling the wrong field; API consumers sending { username } instead of { email }.

Related errors


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/8ec8b23f6df01073. Report an issue: GitHub.

Appendix: source

Thrown at packages/backend/server/src/core/utils/validators.ts:8

import z from 'zod';

import { InvalidEmail, InvalidPasswordLength } from '../../base';

export function assertValidEmail(email: string) {
  const result = z.string().email().safeParse(email);
  if (!result.success) {
    throw new InvalidEmail({ email });
  }
}

export function assertValidPassword(
  password: string,
  { min, max }: { min: number; max: number }
) {
  const result = z.string().min(min).max(max).safeParse(password);

  if (!result.success) {
    throw new InvalidPasswordLength({ min, max });
  }
}

export const validators = {
  assertValidEmail,
  assertValidPassword,
};

View on GitHub (pinned to b4c8548c09)