immich-app/immich · error · BadRequestException

Admin setup is not available

Error message

Admin setup is not available

What it means

Thrown by BaseService.requireSetupAvailable. Setup is allowed only when configRepository.getEnv().setup.allow is true AND no admin user exists yet (userRepository.hasAdmin() is false). If either condition fails, initial admin registration is closed.

Source

Thrown at server/src/services/base.service.ts:291

    return updateConfig(this.configRepos, newConfig);
  }

  requireAccess(request: AccessRequest) {
    return requireAccess(this.accessRepository, request);
  }

  checkAccess(request: AccessRequest) {
    return checkAccess(this.accessRepository, request);
  }

  async isSetupAvailable(): Promise<boolean> {
    const { setup } = this.configRepository.getEnv();
    return setup.allow && !(await this.userRepository.hasAdmin());
  }

  async requireSetupAvailable(): Promise<void> {
    if (!(await this.isSetupAvailable())) {
      throw new BadRequestException('Admin setup is not available');
    }
  }

  async createUser(dto: Insertable<UserTable> & { email: string }): Promise<UserAdmin> {
    const exists = await this.userRepository.getByEmail(dto.email);
    if (exists) {
      this.logger.debug('User creation rejected: user already exists');
      throw new BadRequestException('Email is not available');
    }

    if (!dto.isAdmin) {
      const localAdmin = await this.userRepository.getAdmin();
      if (!localAdmin) {
        throw new BadRequestException('The first registered account must the administrator.');
      }
    }

    const payload: Insertable<UserTable> = { ...dto };

View on GitHub (pinned to 199723261c)

Solutions

  1. Call isSetupAvailable() first and only expose the setup UI when it returns true.
  2. If re-onboarding is genuinely intended, remove/disable the existing admin (or restore an empty DB) so hasAdmin() returns false.
  3. Check that the env/CLI configuration that gates setup.allow is set as intended for this deployment.

Example fix

// before
await userService.requireSetupAvailable();
await userService.createUser(dto);

// after
if (!(await userService.isSetupAvailable())) {
  throw new BadRequestException('Setup already complete or disabled in this environment.');
}
await userService.createUser(dto);
Defensive patterns

Strategy: validation

Validate before calling

if (!(await userService.isSetupAvailable())) {
  // hide the setup screen / return early instead of calling requireSetupAvailable()
  return;
}

Prevention

When it happens

Trigger: Calling the admin-setup/registration endpoint after an admin already exists, or when the environment explicitly disabled setup (setup.allow = false).

Common situations: Hitting the onboarding flow a second time after initial setup completed; a deployment flag/CLI arg disabled setup; an imported backup already contained an admin user.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/1cb70c7d78572935. Report an issue: GitHub.