immich-app/immich · warning
Skipping unknown job
Error message
Skipping unknown job: "${name}" What it means
Job items dispatched to the queue are matched against the registered handlers map. If a job with the given name arrives with no registered handler, the repository logs this warning and returns JobStatus.Skipped instead of throwing. Usually means a job was enqueued under a name the running code doesn't know.
Solutions
- Update all Immich containers to the same version so job names and handlers match
- Clear stale jobs from the Redis queue (or let them drain/skip)
- Verify the microservices process started with the full handler registry (check for startup errors in the worker)
- Re-trigger the intended operation from the UI/API after upgrading
Example fix
// before: mixed versions
IMMICH_VERSION: v1.90.0 # server
IMMICH_VERSION: v1.89.0 # microservices
// after
IMMICH_VERSION: v1.90.0 # same tag for all services (use ${IMMICH_VERSION:-release}) Defensive patterns
Strategy: type-guard
Validate before calling
const knownJobs: JobName[] = Object.values(JobName);
function assertJobKnown(name: string): asserts name is JobName {
if (!knownJobs.includes(name as JobName)) {
throw new Error(`Unknown job name: ${name} — likely version skew between containers`);
}
} Type guard
function isKnownJob(name: string): name is JobName {
return name in (jobRepository as any).handlers;
} Try / catch
try {
const status = await jobRepository.run(jobItem);
if (status === JobStatus.Skipped) {
logger.warn(`Job ${jobItem.name} skipped: handler missing — update all services to the same version`);
}
} catch (err) { logger.error(err); } Prevention
- Pin identical IMMICH_VERSION across all Immich containers
- Flush stale Redis queues after major upgrades
- Register every JobName handler in one module to keep the map exhaustive
- Handle JobStatus.Skipped explicitly in callers
When it happens
Trigger: run() receives a JobItem whose name is not a key in this.handlers — e.g. a job name from a newer/older Immich version, or the worker process lacks the module that registers the handler.
Common situations: Version skew: server upgraded but microservices container still running old image (or vice versa); stale jobs left in Redis from a previous version with removed job names; custom/renamed job names.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Could not find asset
- Failed to add job handler for
- Failed to find job handler for Job.
- No microservices worker is connected. Background jobs will…
- Thumbnail generation failed for asset
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/6e1536cd15258ae0.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/repositories/job.repository.ts:140
return;
}
if (this.microservicesPresent !== isPresent) {
if (isPresent) {
this.logger.log('Microservices worker connected.');
} else {
this.logger.warn(
'No microservices worker is connected. Background jobs will not be processed until one is running.',
);
}
}
this.microservicesPresent = isPresent;
}
async run({ name, data }: JobItem) {
const item = this.handlers[name as JobName];
if (!item) {
this.logger.warn(`Skipping unknown job: "${name}"`);
return JobStatus.Skipped;
}
return item.handler(data);
}
setConcurrency(queueName: QueueName, concurrency: number) {
const worker = this.workers[queueName];
if (!worker) {
this.logger.warn(`Unable to set queue concurrency, worker not found: '${queueName}'`);
return;
}
worker.concurrency = concurrency;
}
async isActive(name: QueueName): Promise<boolean> {
const queue = this.getQueue(name);View on GitHub (pinned to e55ac299a4)