{"record":{"id":"d925507b9bc64421","repo":"immich-app/immich","slug":"not-in-maintenance-mode-d92550","errorCode":null,"errorMessage":"Not in maintenance mode","messagePattern":"Not in maintenance mode","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/maintenance.service.ts","lineNumber":85,"sourceCode":"    );\n  }\n\n  @OnEvent({ name: 'AppRestart', server: true })\n  onRestart(event: ArgOf<'AppRestart'>, ack?: (ok: 'ok') => void): void {\n    this.logger.log(`Restarting due to event... ${JSON.stringify(event)}`);\n\n    ack?.('ok');\n    this.appRepository.exitApp();\n  }\n\n  async createLoginUrl(auth: MaintenanceAuthDto, secret?: string): Promise<string> {\n    const { server } = await this.getConfig({ withCache: true });\n    const baseUrl = getExternalDomain(server);\n\n    if (!secret) {\n      const state = await this.getMaintenanceMode();\n      if (!state.isMaintenanceMode) {\n        throw new Error('Not in maintenance mode');\n      }\n\n      secret = state.secret;\n    }\n\n    return await createMaintenanceLoginUrl(baseUrl, auth, secret);\n  }\n}\n","sourceCodeStart":67,"sourceCodeEnd":94,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/maintenance.service.ts#L67-L94","documentation":"MaintenanceService.createLoginUrl builds a one-time admin login URL for maintenance mode. When called without an explicit secret, it reads the current maintenance-mode state and uses state.secret. If maintenance mode is not currently active, there is no secret to use, so it throws a plain Error 'Not in maintenance mode'. This guards against generating URLs that could never authenticate.","triggerScenarios":"Calling createLoginUrl(auth, undefined-secret) while getMaintenanceMode().isMaintenanceMode is false. E.g. an admin flow that generates the URL after maintenance mode was already turned off, or a scripted call outside a maintenance window.","commonSituations":"Race between turning off maintenance mode and a lingering UI action; calling the maintenance login endpoint outside maintenance; automation that does not check mode first.","solutions":["Enable maintenance mode first (set isMaintenanceMode true), then call createLoginUrl without a secret.","Or supply the secret explicitly to createLoginUrl if you hold one from when maintenance mode was enabled.","Have callers check getMaintenanceMode() before requesting the URL.","If maintenance ended, use the normal admin login flow instead."],"exampleFix":"// before\nawait maintenanceApi.createLoginUrl(auth); // not in maintenance mode\n// after\nawait maintenanceApi.setMaintenanceMode(true);\nawait maintenanceApi.createLoginUrl(auth);","handlingStrategy":"validation","validationCode":"const state = await api.maintenanceApi.getMaintenanceMode();\nif (!state.isMaintenanceMode) {\n  throw new Error('Enable maintenance mode before requesting a maintenance login URL');\n}\nawait api.maintenanceApi.createLoginUrl(auth);","typeGuard":"const isInMaintenanceMode = (s: { isMaintenanceMode: boolean }) =>\n  s.isMaintenanceMode === true;","tryCatchPattern":"try {\n  return await api.maintenanceApi.createLoginUrl(auth);\n} catch (e) {\n  if (/Not in maintenance mode/.test(String(e?.message))) {\n    // either enable maintenance mode or pass an explicit secret\n  } else throw e;\n}","preventionTips":["Check getMaintenanceMode() before requesting the URL.","Pass an explicit secret if you hold one instead of relying on current state.","Use the normal admin login outside maintenance windows."],"tags":["maintenance","auth","admin","state","immich","nestjs"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}