toeverything/AFFiNE · error · PasswordRequired

password_required

password_required

Error message

Password is required.

What it means

PasswordRequired thrown at packages/backend/server/src/core/selfhost/controller.ts:48 when the create-admin request body has no password (falsy). It is a plain required-field guard that runs before assertValidPassword applies the configured password policy.

Solutions

  1. Send a non-empty password field in the JSON body.
  2. Ensure the value survives any proxy/serializer untouched.

Example fix

// before
await api.createAdmin({ name, email }); // password missing

// after
await api.createAdmin({ name, email, password }); // non-empty string
Defensive patterns

Strategy: validation

Validate before calling

if (typeof password !== 'string' || password.length === 0) {
  return setFieldError('password', 'Password is required.');
}

Type guard

const isPasswordRequired = (e: unknown): e is PasswordRequired =>
  e instanceof PasswordRequired;

Try / catch

try {
  await api.createAdmin({ name, email, password });
} catch (e) {
  if (e instanceof PasswordRequired) return setFieldError('password', e.message);
  throw e;
}

Prevention

When it happens

Trigger: POST /create-admin-user with password omitted, an empty string, or a body key typo such as pwd/pass.

Common situations: Setup form not binding the password input, a proxy renaming JSON fields, or provisioning scripts that only send email/name.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of toeverything/AFFiNE@2af30773ae (2026-08-18). Data as JSON: /api/errors/5cee75a5e36e807d. Report an issue: GitHub.

Appendix: source

Thrown at packages/backend/server/src/core/selfhost/controller.ts:49

    private readonly mutex: Mutex,
    private readonly server: ServerService
  ) {}

  @Public()
  @Post('/create-admin-user')
  async createAdmin(
    @Req() req: Request,
    @Res() res: Response,
    @Body() input: CreateUserInput
  ) {
    if (await this.server.initialized()) {
      throw new ActionForbidden('First user already created');
    }

    validators.assertValidEmail(input.email);

    if (!input.password) {
      throw new PasswordRequired();
    }

    validators.assertValidPassword(
      input.password,
      this.config.auth.passwordRequirements
    );

    await using lock = await this.mutex.acquire('createFirstAdmin');

    if (!lock) {
      throw new InternalServerError();
    }
    const user = await this.models.user.create({
      name: input.name || undefined,
      email: input.email,
      password: input.password,
      registered: true,
    });

View on GitHub (pinned to 2af30773ae)