toeverything/AFFiNE · critical · SignUpForbidden

sign_up_forbidden

sign_up_forbidden

Error message

sign up helper is forbidden for non-test environment

What it means

Thrown by AuthService.signUp, an explicitly @deprecated test-only helper, when invoked outside the test environment (env.testing is false). Category 'action_forbidden', code 'sign_up_forbidden'. The check exists so this shortcut (which bypasses invitations, verification, and rate limiting) can never leak into production.

Source

Thrown at packages/backend/server/src/core/auth/service.ts:84

  async onApplicationBootstrap() {
    if (env.dev) {
      await createDevUsers(this.models, this.entitlement);
    }
  }

  async canSignIn(_email: string) {
    // may add more sign-in check later
    return true;
  }

  /**
   * @deprecated
   *
   * This is a test only helper to quickly signup a user, do not use in production
   */
  async signUp(email: string, password: string): Promise<CurrentUser> {
    if (!env.testing) {
      throw new SignUpForbidden(
        'sign up helper is forbidden for non-test environment'
      );
    }

    return this.models.user
      .create({
        email,
        password,
      })
      .then(sessionUser);
  }

  async signIn(email: string, password: string): Promise<CurrentUser> {
    return this.models.user.signIn(email, password).then(sessionUser);
  }

  async verifyPassword(
    email: string,

View on GitHub (pinned to 26c515e050)

Solutions

  1. Replace the signUp call with the real registration path (invitation accept / sign-up mutation) appropriate to the environment.
  2. If this is genuinely test scaffolding, ensure the process runs with env.testing=true (e.g. NODE_ENV=test) and the config loader exposes it.
  3. Remove the reference entirely; the method is @deprecated.

Example fix

// before (in a seed script run against staging)
await auth.signUp(user.email, user.password);

// after (use the real resolver or restrict to test)
if (process.env.NODE_ENV === 'test') {
  await auth.signUp(user.email, user.password);
} else {
  throw new Error('Use the invite/sign-up mutation in non-test envs');
}
Defensive patterns

Strategy: validation

Validate before calling

import { env } from '../../base/env';
function assertTestEnvForSignUp(): void {
  if (!env.testing) {
    throw new Error('auth.signUp is a test-only helper; use the real sign-up/invitation flow.');
  }
}
assertTestEnvForSignUp();
await auth.signUp(email, password);

Type guard

function isTestEnv(): boolean {
  return Boolean(env.testing);
}

Prevention

When it happens

Trigger: Calling AuthService.signUp(email, password) (service.ts:78-86) in any process where env.testing !== true. The guard is the very first statement, so any non-test caller fails immediately.

Common situations: A developer copied test seed logic into a script/migration/seeder that runs against a non-test database; a feature flag or env mislabel that left signUp referenced in production code paths; an e2e harness pointed at a staging env that does not set NODE_ENV=test.

Understand the failure class

Related errors


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