{"record":{"id":"1a3c532eb0f9816c","repo":"immich-app/immich","slug":"the-first-registered-account-must-the-administrato","errorCode":null,"errorMessage":"The first registered account must the administrator.","messagePattern":"The first registered account must the administrator\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/base.service.ts","lineNumber":313,"sourceCode":"  }\n\n  async requireSetupAvailable(): Promise<void> {\n    if (!(await this.isSetupAvailable())) {\n      throw new BadRequestException('Admin setup is not available');\n    }\n  }\n\n  async createUser(dto: Omit<Insertable<UserTable>, 'clusterGroupId'> & { email: string }): Promise<UserAdmin> {\n    const exists = await this.userRepository.getByEmail(dto.email);\n    if (exists) {\n      this.logger.debug('User creation rejected: user already exists');\n      throw new BadRequestException('Email is not available');\n    }\n\n    if (!dto.isAdmin) {\n      const localAdmin = await this.userRepository.getAdmin();\n      if (!localAdmin) {\n        throw new BadRequestException('The first registered account must the administrator.');\n      }\n    }\n\n    const payload: Omit<Insertable<UserTable>, 'clusterGroupId'> = { ...dto };\n    if (payload.password) {\n      payload.password = await this.cryptoRepository.hashBcrypt(payload.password, SALT_ROUNDS);\n    }\n    if (payload.storageLabel) {\n      payload.storageLabel = sanitize(payload.storageLabel.replaceAll('.', ''));\n    }\n\n    const clusterGroup = await this.clusterGroupRepository.create();\n    const user = await this.userRepository.create({ ...payload, clusterGroupId: clusterGroup.id });\n\n    await this.eventRepository.emit('UserCreate', user);\n\n    return user;\n  }","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/base.service.ts#L295-L331","documentation":"Immich requires that the very first user account created in the system is the administrator. When creating a user with isAdmin=false (or unset), the service checks userRepository.getAdmin(); if no admin exists yet, creation of a non-admin account is rejected with this BadRequestException. This guarantees a bootstrap admin always exists.","triggerScenarios":"Calling POST /api/admin/users (createUser) with dto.isAdmin=false (or omitted) while no administrator account exists in the database yet.","commonSituations":"Fresh Immich installs where the first API-created user is a regular user; scripts provisioning users before the setup wizard has created the admin; restored databases where the admin row was dropped.","solutions":["Create the first account with isAdmin=true so it becomes the administrator.","Verify an admin exists: run the server's admin-check or query the user table for a row with is_admin=true.","If the admin was deleted, restore it or re-run initial setup before adding regular users."],"exampleFix":"// before\nawait api.createUser({ email: 'bob@example.com', password: 'pw', name: 'Bob' }); // isAdmin defaults to false\n// after\nawait api.createUser({ email: 'admin@example.com', password: 'pw', name: 'Admin', isAdmin: true }); // first user must be admin","handlingStrategy":"validation","validationCode":"// Before creating a user, check whether an admin already exists\nconst hasAdmin = (await api.searchUsers()).some(u => u.isAdmin);\nif (!hasAdmin) {\n  dto.isAdmin = true; // first user must be the administrator\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always bootstrap with an admin account before provisioning regular users.","When scripting user creation on a fresh instance, set isAdmin=true for the first call.","Never delete the last admin account; promote a replacement first."],"tags":["user-management","bootstrap","bad-request","admin-required"],"backgroundTag":"invalid-state-transition","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}