{"record":{"id":"9e5a44a68f9049a7","repo":"immich-app/immich","slug":"invalid-backup-name","errorCode":null,"errorMessage":"Invalid backup name!","messagePattern":"Invalid backup name!","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/database-backup.service.ts","lineNumber":265,"sourceCode":"      await this.storageRepository.rename(temporaryFilePath, backupFilePath);\n    } catch (error) {\n      this.logger.error(`Database Backup Failure: ${error}`);\n      await this.storageRepository\n        .unlink(temporaryFilePath)\n\n        .catch((error) => this.logger.error(`Failed to delete failed backup file: ${error}`));\n      throw error;\n    }\n\n    this.logger.log(`Database Backup Success`);\n    return backupFilePath;\n  }\n\n  async uploadBackup(file: Express.Multer.File): Promise<void> {\n    const backupsFolder = StorageCore.getBaseFolder(StorageFolder.Backups);\n    const fn = basename(file.originalname);\n    if (!isValidDatabaseBackupName(fn)) {\n      throw new BadRequestException('Invalid backup name!');\n    }\n\n    const filePath = path.join(backupsFolder, `uploaded-${fn}`);\n    await this.storageRepository.createOrOverwriteFile(filePath, file.buffer);\n  }\n\n  downloadBackup(fileName: string): ImmichFileResponse {\n    if (!isValidDatabaseBackupName(fileName)) {\n      throw new BadRequestException('Invalid backup name!');\n    }\n\n    const filePath = path.join(StorageCore.getBaseFolder(StorageFolder.Backups), fileName);\n\n    return {\n      path: filePath,\n      fileName,\n      cacheControl: CacheControl.PrivateWithoutCache,\n      contentType: fileName.endsWith('.gz') ? 'application/gzip' : 'application/sql',","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/database-backup.service.ts#L247-L283","documentation":"Thrown by DatabaseBackupService.uploadBackup (BadRequestException). The uploaded file's basename must match /^\\d\\w.-]+\\.sql(?:\\.gz)?$/: only word characters, digits, hyphens and dots, ending in '.sql' or '.sql.gz'. Any other name is rejected before the file is written to the backups folder.","triggerScenarios":"Uploading a backup whose original filename contains spaces, path separators, unusual extensions (e.g. .zip, .bak, .dump), or lacks the .sql/.sql.gz suffix.","commonSituations":"User renames a dump to something descriptive ('My Backup July.sql'); zipped/tarred dump (.zip); filename with spaces or unicode; case issues like '.SQL'.","solutions":["Rename the file to match <name>.sql.gz (or .sql), ASCII only, no spaces.","If the file is gzipped, ensure the extension is exactly '.sql.gz'.","Validate the filename client-side before upload using the same regex."],"exampleFix":"// before\nconst fd = new FormData(); fd.append('file', rawFile); await upload(fd);\n\n// after\nconst VALID = /^[\\w\\d.-]+\\.sql(?:\\.gz)?$/;\nif (!VALID.test(rawFile.name)) {\n  throw new Error(`Backup filename must match ${VALID}`);\n}\nconst fd = new FormData(); fd.append('file', rawFile); await upload(fd);","handlingStrategy":"type-guard","validationCode":"const VALID = /^[\\w\\d.-]+\\.sql(?:\\.gz)?$/;\nif (!VALID.test(file.originalname)) {\n  throw new BadRequestException('Backup must be named <name>.sql or <name>.sql.gz');\n}","typeGuard":"function isValidBackupName(name: string): boolean {\n  return /^[\\w\\d.-]+\\.sql(?:\\.gz)?$/.test(name);\n}","tryCatchPattern":null,"preventionTips":["Rename dumps to ASCII <name>.sql.gz before upload.","Validate filenames client-side with the same regex.","Avoid spaces, unicode, and non-sql extensions in backup names."],"tags":["database","backup","upload","validation","filename"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}