toeverything/AFFiNE · error · InvalidEmail

invalid_email

invalid_email

Error message

An invalid email provided: ${email}

What it means

Thrown by the `POST /api/auth/preflight` handler when the request body fails `AuthPreflightBodySchema.safeParse`. The schema is `{ email: z.string().max(320) }.strict()`, so a missing `email` field, an extra unknown field, or a non-string body all fail. The message reports `email: 'not provided'` to distinguish this from a syntactically bad email (which is caught next by `assertValidEmail`). HTTP 400.

Source

Thrown at packages/backend/server/src/core/auth/controller.ts:97

    private readonly config: Config
  ) {
    if (env.dev) {
      // set DNS servers in dev mode
      // NOTE: some network debugging software uses DNS hijacking
      // to better debug traffic, but their DNS servers may not
      // handle the non dns query(like txt, mx) correctly, so we
      // set a public DNS server here to avoid this issue.
      setServers(['1.1.1.1', '8.8.8.8']);
    }
  }

  @Public()
  @UseNamedGuard('version')
  @Post('/preflight')
  async preflight(@Body() body?: unknown): Promise<PreflightResponse> {
    const input = AuthPreflightBodySchema.safeParse(body);
    if (!input.success) {
      throw new InvalidEmail({ email: 'not provided' });
    }
    validators.assertValidEmail(input.data.email);

    return this.authMethods.loginPreflight(input.data.email);
  }

  @UseNamedGuard('version')
  @Get('/methods')
  async boundMethods(@CurrentUser() user: CurrentUser) {
    return this.authMethods.boundMethods(user.id);
  }

  @Public()
  @UseNamedGuard('version', 'captcha')
  @Post('/sign-in')
  @Header('content-type', 'application/json')
  async signIn(
    @Req() req: Request,

View on GitHub (pinned to 26c515e050)

Solutions

  1. Send a body that matches `{ email: string }` exactly — no extra keys.
  2. Validate on the client before posting: ensure `email` is a non-empty string ≤ 320 chars.
  3. If you added a new field, update `AuthPreflightBodySchema` rather than sending undeclared fields.

Example fix

// before
fetch('/api/auth/preflight', { method: 'POST', body: '{}' });

// after
fetch('/api/auth/preflight', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ email: userInput.value }),
});
Defensive patterns

Strategy: validation

Validate before calling

import { z } from 'zod';
const Preflight = z.object({ email: z.string().min(1).max(320) }).strict();
const parsed = Preflight.safeParse(body);
if (!parsed.success) throw new Error('email required');
await fetch('/api/auth/preflight', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify(parsed.data),
});

Type guard

function isPreflightBody(v: unknown): v is { email: string } {
  return typeof v === 'object' && v !== null &&
    typeof (v as any).email === 'string' && (v as any).email.length > 0 &&
    (v as any).email.length <= 320;
}

Prevention

When it happens

Trigger: Calling `/preflight` with an empty body `{}`, omitting the `email` field, sending `email` as null/number, or including extra fields rejected by `.strict()` (e.g. legacy `captcha` field).

Common situations: Frontend form submitted before the email input was filled, a malformed fetch payload, an integration test posting the wrong shape, or a client version mismatch sending fields the strict schema rejects.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/a6f2871eeb80bda0. Report an issue: GitHub.