immich-app/immich · error · BadRequestException
Invalid job name
Error message
Invalid job name
What it means
asJobItem is a switch over ManualJobName values that maps each manual job handle to a concrete JobName plus payload; the default branch throws this error when a caller passes a manual-job identifier that has no case in the switch. It fires whenever a new ManualJobName enum member is added without extending the mapping, or when a stale/unknown string is submitted through the create flow, so it signals a programming/migration gap rather than user input problems.
Solutions
- Add a case for the unrecognized ManualJobName in asJobItem mapping it to the correct JobName and data payload
- Verify the client/API is sending a ManualJobName value that exists in the current enum version
- Check for enum drift between the API version receiving the request and the server code handling it
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at server/src/services/job.service.ts:74 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/14f449bc0e8e09ac.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/job.service.ts:74
case ManualJobName.IntegrityChecksumFilesRefresh: {
return { name: JobName.IntegrityChecksumFiles, data: { refreshOnly: true } };
}
case ManualJobName.IntegrityMissingFilesDeleteAll: {
return { name: JobName.IntegrityDeleteReportType, data: { type: IntegrityReport.MissingFile } };
}
case ManualJobName.IntegrityUntrackedFilesDeleteAll: {
return { name: JobName.IntegrityDeleteReportType, data: { type: IntegrityReport.UntrackedFile } };
}
case ManualJobName.IntegrityChecksumFilesDeleteAll: {
return { name: JobName.IntegrityDeleteReportType, data: { type: IntegrityReport.ChecksumFail } };
}
default: {
throw new BadRequestException('Invalid job name');
}
}
};
@Injectable()
export class JobService extends BaseService {
async create(dto: JobCreateDto): Promise<void> {
await this.jobRepository.queue(asJobItem(dto));
}
@OnEvent({ name: 'JobRun' })
async onJobRun(...[queueName, job]: ArgsOf<'JobRun'>) {
try {
await this.eventRepository.emit('JobStart', queueName, job);
const response = await this.jobRepository.run(job);
await this.eventRepository.emit('JobSuccess', { job, response });
if (response && typeof response === 'string' && [JobStatus.Success, JobStatus.Skipped].includes(response)) {
await this.onDone(job);View on GitHub (pinned to e55ac299a4)