{"record":{"id":"c03fdb9d2e44d703","repo":"immich-app/immich","slug":"invalid-job-name-name","errorCode":null,"errorMessage":"Invalid job name: ${name}","messagePattern":"Invalid job name: (.+?)","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/queue.service.ts","lineNumber":249,"sourceCode":"\n      case QueueName.FacialRecognition: {\n        return this.jobRepository.queue({ name: JobName.FacialRecognitionQueueAll, data: { force } });\n      }\n\n      case QueueName.Library: {\n        return this.jobRepository.queue({ name: JobName.LibraryScanQueueAll, data: { force } });\n      }\n\n      case QueueName.BackupDatabase: {\n        return this.jobRepository.queue({ name: JobName.DatabaseBackup, data: { force } });\n      }\n\n      case QueueName.Ocr: {\n        return this.jobRepository.queue({ name: JobName.OcrQueueAll, data: { force } });\n      }\n\n      default: {\n        throw new BadRequestException(`Invalid job name: ${name}`);\n      }\n    }\n  }\n\n  private isConcurrentQueue(name: QueueName): name is ConcurrentQueueName {\n    return ![\n      QueueName.FacialRecognition,\n      QueueName.StorageTemplateMigration,\n      QueueName.DuplicateDetection,\n      QueueName.BackupDatabase,\n    ].includes(name);\n  }\n\n  async handleNightlyJobs() {\n    const config = await this.getConfig({ withCache: false });\n    const jobs: JobItem[] = [];\n\n    if (config.nightlyTasks.databaseCleanup) {","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/queue.service.ts#L231-L267","documentation":"The legacy `start` switch only maps known QueueName values to concrete jobs; any queue name falling through to `default` throws this. It means the caller supplied a name that is not a runnable job target in this code path.","triggerScenarios":"Calling runCommandLegacy/start with a queue name outside the handled cases (e.g. BackgroundTask, Threading-style concurrent queues, or a misspelled/renamed queue name).","commonSituations":"Version drift: client hardcoded a queue name removed/renamed in a newer server; automation scripts enumerating all QueueName values and trying to start every one; typos in admin tooling.","solutions":["Use only the queue names the legacy start path supports (video conversion, thumbnail generation, library scan, etc.)","Update client scripts to the queue names of the deployed server version","For concurrent queues use the queue update/resume endpoints instead of job start","Log and inspect the `name` value to catch typos"],"exampleFix":"// before\nawait api.runJob('backgroundTask' as any); // Invalid job name\n// after\nawait api.runJob('videoConversion'); // a supported job name","handlingStrategy":"validation","validationCode":"const STARTABLE: QueueName[] = ['videoConversion','thumbnailGeneration','libraryScan','libraryDelete','migration','generateMemories','backupDatabase'];\nif (!STARTABLE.includes(name)) throw new InvalidJobName(name);","typeGuard":"function isStartableQueue(name: string): name is QueueName {\n  return ['videoConversion','thumbnailGeneration','libraryScan','libraryDelete','migration','generateMemories','backupDatabase'].includes(name);\n}","tryCatchPattern":"try {\n  await queueService.start(auth, name, dto);\n} catch (e) {\n  if (e instanceof BadRequestException && e.message.startsWith('Invalid job name')) {\n    logger.error(`Unsupported job: ${name}`);\n    return;\n  }\n  throw e;\n}","preventionTips":["Keep client-side queue-name enums in sync with the server version","Whitelist startable queue names in automation scripts","Validate names against the server's advertised job list"],"tags":["queue","invalid-argument","enum"],"backgroundTag":"invalid-enum-value","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"}