toeverything/AFFiNE · error · WrongSignInCredentials

wrong_sign_in_credentials

wrong_sign_in_credentials

Error message

Wrong user email or password: ${email}

What it means

During magic-link send, a user matching the email is found but has disabled=true in the users table. Rather than reveal the account is disabled, the server throws WrongSignInCredentials with the email — the same shape used for invalid credentials — to avoid account enumeration. Category maps to wrong_sign_in_credentials.

Source

Thrown at packages/backend/server/src/core/auth/magic-link.ts:62

    const callbackUrlObj = this.url.url(callbackUrl);
    const redirectUriInCallback =
      callbackUrlObj.searchParams.get('redirect_uri');
    if (
      redirectUriInCallback &&
      !this.url.isAllowedRedirectUri(redirectUriInCallback)
    ) {
      throw new ActionForbidden();
    }

    const user = await this.models.user.getUserByEmail(email, {
      withDisabled: true,
    });

    if (!user) {
      await this.assertSignupAllowed(email);
    } else if (user.disabled) {
      throw new WrongSignInCredentials({ email });
    }

    const ttlInSec = 30 * 60;
    const { token, expiresAt: tokenExpiresAt } =
      await this.models.verificationToken.createWithExpiresAt(
        TokenType.SignIn,
        email,
        ttlInSec
      );

    const otp = this.crypto.otp();
    const { expiresAt: otpExpiresAt } = await this.models.magicLinkOtp.upsert(
      email,
      otp,
      token,
      clientNonce
    );

View on GitHub (pinned to 26c515e050)

Solutions

  1. Have an admin re-enable the account (clear the disabled flag) if access should be restored.
  2. If the user should not have access, treat this as expected and show a generic 'wrong credentials' message to the user.
  3. Do not attempt to sign up a new account with the same email; the existing disabled record blocks it.
  4. Audit admin actions / the users table to confirm the disabled flag's intended state.
Defensive patterns

Strategy: try-catch

Type guard

function isWrongSignInCredentials(err: unknown): boolean {
  return (
    !!err &&
    typeof err === 'object' &&
    (err as { code?: string }).code === 'wrong_sign_in_credentials'
  );
}

Try / catch

try {
  await magicLink.send(email);
} catch (err) {
  if (isWrongSignInCredentials(err)) {
    showGenericError('Wrong email or credentials.');
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling MagicLinkAuthService.send with an email whose user row exists and disabled=true (set by an admin via disableUser or equivalent). The check happens after callback/redirect validation and after confirming the user exists with withDisabled:true.

Common situations: An admin suspended the user but they still try to sign in via magic link. A disabled account leftover from a data import. Self-hosted ops flipped the disabled flag manually.

Related errors


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