{"record":{"id":"65346ab616d4eef3","repo":"immich-app/immich","slug":"not-in-maintenance-mode","errorCode":null,"errorMessage":"Not in maintenance mode","messagePattern":"Not in maintenance mode","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"server/src/controllers/maintenance.controller.ts","lineNumber":54,"sourceCode":"  @Endpoint({\n    summary: 'Detect existing install',\n    description: 'Collect integrity checks and other heuristics about local data.',\n    history: new HistoryBuilder().added('v2.5.0').alpha('v2.5.0'),\n  })\n  @Authenticated({ permission: Permission.Maintenance, admin: true })\n  detectPriorInstall(): Promise<MaintenanceDetectInstallResponseDto> {\n    return this.service.detectPriorInstall();\n  }\n\n  @Post('login')\n  @Endpoint({\n    summary: 'Log into maintenance mode',\n    description: 'Login with maintenance token or cookie to receive current information and perform further actions.',\n    history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),\n  })\n  @Authenticated({ public: true })\n  maintenanceLogin(@Body() _dto: MaintenanceLoginDto): MaintenanceAuthDto {\n    throw new BadRequestException('Not in maintenance mode');\n  }\n\n  @Post()\n  @Endpoint({\n    summary: 'Set maintenance mode',\n    description: 'Put Immich into or take it out of maintenance mode',\n    history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),\n  })\n  @Authenticated({ permission: Permission.Maintenance, admin: true })\n  async setMaintenanceMode(\n    @Auth() auth: AuthDto,\n    @Body() dto: SetMaintenanceModeDto,\n    @GetLoginDetails() loginDetails: LoginDetails,\n    @Res({ passthrough: true }) res: Response,\n  ): Promise<void> {\n    if (dto.action === MaintenanceAction.End) {\n      return;\n    }","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/controllers/maintenance.controller.ts#L36-L72","documentation":"The POST /maintenance/login controller method maintenanceLogin unconditionally throws BadRequestException('Not in maintenance mode'). The real login logic lives in the maintenance worker service and only runs when the server boots in maintenance mode; this controller stub exists so the OpenAPI route is always documented. Hitting it on a normally-running server is expected to fail.","triggerScenarios":"Sending POST /maintenance/login (with a maintenance token/cookie body) against an Immich server that is NOT started in maintenance mode.","commonSituations":"Operator forgets to start the container/process with the maintenance flag; the endpoint is hit by automation/probes during normal operation; confusion about whether the server is currently in maintenance.","solutions":["Restart Immich in maintenance mode (set the maintenance worker / boot flag as documented for your install) before calling login.","If you did not intend to be in maintenance, do not call this endpoint; use normal auth flows instead.","Check server status via the maintenance status endpoint to confirm the current mode before attempting login."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// call status endpoint before login to confirm mode\nconst status = await fetch(`${baseUrl}/maintenance/status`).then(r => r.json());\nif (!status.maintenanceEnabled) {\n  throw new Error('Server is not in maintenance mode; restart it in maintenance first.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await fetch(`${baseUrl}/maintenance/login`, { method: 'POST', body });\n} catch (e) {\n  if ((e as Error).message.includes('Not in maintenance mode')) {\n    // restart server in maintenance, or switch to normal auth\n  } else throw e;\n}","preventionTips":["Confirm maintenance mode via the status endpoint before calling login.","Only call /maintenance/login when an operator has intentionally booted maintenance.","Keep automation aware of the maintenance flag via status checks, not blind calls."],"tags":["maintenance","api","nest","startup-state"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}