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
- Send a non-empty password field in the JSON body.
- 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
- Require the password field client-side before enabling submit.
- Validate against the same passwordRequirements config the server enforces.
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)