{"record":{"id":"1cb70c7d78572935","repo":"immich-app/immich","slug":"admin-setup-is-not-available","errorCode":null,"errorMessage":"Admin setup is not available","messagePattern":"Admin setup is not available","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/base.service.ts","lineNumber":299,"sourceCode":"    return updateConfig(this.configRepos, newConfig);\n  }\n\n  requireAccess(request: AccessRequest) {\n    return requireAccess(this.accessRepository, request);\n  }\n\n  checkAccess(request: AccessRequest) {\n    return checkAccess(this.accessRepository, request);\n  }\n\n  async isSetupAvailable(): Promise<boolean> {\n    const { setup } = this.configRepository.getEnv();\n    return setup.allow && !(await this.userRepository.hasAdmin());\n  }\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 };","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/base.service.ts#L281-L317","documentation":"requireSetupAvailable checks that the server's setup flag is enabled (allow) and that no admin user exists yet (userRepository.hasAdmin). Admin-creation/setup endpoints call it first; once setup is done or disallowed, any attempt throws BadRequestException('Admin setup is not available').","triggerScenarios":"POST to the admin registration/setup endpoint after an admin already exists, or when server config disables setup.","commonSituations":"Re-running the initial setup wizard on an already-initialized instance; replaying setup requests from automation; IMMICH_CONFIG setup.allow disabled in a new deployment; database restored with existing users.","solutions":["Do not call the setup endpoint again — log in with the existing admin account","Reset admin credentials via the admin CLI/user management instead of setup","If setup was disallowed by config, enable it in the server configuration only for intentional re-init","Verify the correct database; a restored DB may already contain an admin"],"exampleFix":"// before\nawait api.post('/users/admin', adminDto); // setup already done\n// after\nawait api.post('/auth/login', { email, password }); // existing admin","handlingStrategy":"try-catch","validationCode":"const hasAdmin = await userRepository.hasAdmin(); if (hasAdmin) throw new Error('setup already completed');","typeGuard":null,"tryCatchPattern":"catch (e) { if (e.status === 400 && /setup is not available/.test(e.message)) { /* login with existing admin instead */ } }","preventionTips":["Guard setup UI behind a hasAdmin check","Keep setup.allow disabled after init","Track setup completion in deployment state"],"tags":["setup","admin","state"],"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"}