immich-app/immich · warning · BadRequestException
Invalid job name: ${name}
Error message
Invalid job name: ${name} What it means
Thrown by QueueService.start in the default switch case. The name passed through does not match any of the explicitly handled QueueName values (VideoConversion, StorageTemplateMigration, LibraryScanQueueAll, BackupDatabase, Ocr, etc.). BadRequestException with the offending name interpolated -> HTTP 400.
Source
Thrown at server/src/services/queue.service.ts:249
case QueueName.FacialRecognition: {
return this.jobRepository.queue({ name: JobName.FacialRecognitionQueueAll, data: { force } });
}
case QueueName.Library: {
return this.jobRepository.queue({ name: JobName.LibraryScanQueueAll, data: { force } });
}
case QueueName.BackupDatabase: {
return this.jobRepository.queue({ name: JobName.DatabaseBackup, data: { force } });
}
case QueueName.Ocr: {
return this.jobRepository.queue({ name: JobName.OcrQueueAll, data: { force } });
}
default: {
throw new BadRequestException(`Invalid job name: ${name}`);
}
}
}
private isConcurrentQueue(name: QueueName): name is ConcurrentQueueName {
return ![
QueueName.FacialRecognition,
QueueName.StorageTemplateMigration,
QueueName.DuplicateDetection,
QueueName.BackupDatabase,
].includes(name);
}
async handleNightlyJobs() {
const config = await this.getConfig({ withCache: false });
const jobs: JobItem[] = [];
if (config.nightlyTasks.databaseCleanup) {View on GitHub (pinned to 199723261c)
Solutions
- Only call start on queues that have an explicit job to enqueue (see the switch cases).
- Validate the name against the startable subset (concurrent queues + the named serial queues) before calling.
- If a new QueueName was added, extend the switch in QueueService.start to handle it.
Example fix
// before
default: {
throw new BadRequestException(`Invalid job name: ${name}`);
}
// after (list the accepted values)
default: {
throw new BadRequestException(
`Invalid job name: ${name}. Startable queues: videoConversion, storageTemplateMigration, library, backupDatabase, ocr, ...`,
);
} Defensive patterns
Strategy: validation
Validate before calling
// Validate against the startable set before calling start.
const STARTABLE = new Set([
'videoConversion','storageTemplateMigration','library',
'backupDatabase','ocr','thumbnailGeneration','metadataExtraction',
'faceDetection','facialRecognition','smartSearch','duplicateDetection','sidecar',
]);
if (!STARTABLE.has(name)) {
throw new Error(`Queue ${name} has no start handler`);
} Type guard
const isStartableQueue = (name: string): boolean => STARTABLE.has(name);
Try / catch
try {
await queueService.handleCommand(auth, name, dto);
} catch (e) {
if (e instanceof BadRequestException && /Invalid job name/i.test(e.message)) {
// surface the accepted list to the operator
}
throw e;
} Prevention
- Keep a client-side allowlist of startable queue names in sync with QueueService.start.
- When extending QueueName, update the switch in start() in the same change.
- Surface the accepted values in the error message.
When it happens
Trigger: POST start-queue with a QueueName value that exists in the enum but has no start handler (e.g. BackgroundTask, Migration, Search, Sidecar, Workflow, IntegrityCheck, Editor), or with a non-QueueName string that slipped past the schema.
Common situations: Client sends a queue name that is pausable/processable but not startable; enum extended without updating the switch; typo or case mismatch in the queue name.
Related errors
- Invalid job name
- The BackgroundTask queue cannot be paused
- Job is already running
- Unsupported file type ${filename}
- May not request original file
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/c03fdb9d2e44d703.
Report an issue: GitHub.