immich-app/immich · warning

Machine learning request to

Error message

Machine learning request to "${url}" failed with status ${response.status}: ${response.statusText}

What it means

The machine-learning repository calls the ML microservice's /predict endpoint via fetch. When the response is not ok (non-2xx), the call is not retried and this warning is logged; the caller (e.g. smart search / facial recognition job) receives no embedding result for that asset. It is a warning, not a throw — the service degrades gracefully but ML-dependent features fail.

Solutions

  1. Check the machine-learning container logs for the stack trace corresponding to the logged status.
  2. Verify IMMICH_MACHINE_LEARNING_URL points to the correct reachable host:port of the ML service.
  3. Restart the machine-learning container; increase its memory limit if it was OOM-killed.
  4. Ensure server and machine-learning images are the same version.
  5. If status 413/4xx, lower concurrency or image size settings for ML jobs.

Example fix

// before
const response = await fetch(new URL('predict', url), { method: 'POST', body: formData });
// after (add timeout + explicit status logging)
const response = await fetch(new URL('predict', url), { method: 'POST', body: formData, signal: AbortSignal.timeout(30_000) });
if (!response.ok) this.logger.warn(`ML predict failed: ${response.status} ${await response.text()}`);
Defensive patterns

Strategy: retry

Validate before calling

const health = await fetch(new URL('ping', mlUrl)).then(r => r.ok, () => false);
if (!health) throw new Error(`ML server ${mlUrl} not ready`);

Try / catch

try {
  const res = await fetch(new URL('predict', url), { method: 'POST', body: formData, signal: AbortSignal.timeout(30_000) });
  if (!res.ok) throw new Error(`ML ${res.status}: ${res.statusText}`);
  return await res.json();
} catch (e) {
  logger.warn(`ML predict failed, using fallback`, e);
  return null; // degrade: skip smart-search/face features
}

Prevention

When it happens

Trigger: A POST to `${url}predict` with form data returns a non-ok HTTP status (4xx/5xx) from the machine-learning server, e.g. during search indexing or face detection.

Common situations: ML container not fully started or crashed mid-request; model loading failure (OOM) on the ML server; version mismatch between server and ML image; wrong MACHINE_LEARNING_URL/port configured; request payload too large for the ML server.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/ae3342139d5d90b2. Report an issue: GitHub.

Appendix: source

Thrown at server/src/repositories/machine-learning.repository.ts:177

    return this.healthyMap[url];
  }

  private async predict<T>(payload: ModelPayload, config: MachineLearningRequest): Promise<T> {
    const formData = await this.getFormData(payload, config);

    for (const url of [
      // try healthy servers first
      ...this.config.urls.filter((url) => this.isHealthy(url)),
      ...this.config.urls.filter((url) => !this.isHealthy(url)),
    ]) {
      try {
        const response = await fetch(new URL('predict', url), { method: 'POST', body: formData });
        if (response.ok) {
          this.setHealthy(url, true);
          return response.json();
        }

        this.logger.warn(
          `Machine learning request to "${url}" failed with status ${response.status}: ${response.statusText}`,
        );
      } catch (error: Error | unknown) {
        this.logger.warn(`Machine learning request to "${url}" failed`, error);
      }

      this.setHealthy(url, false);
    }

    throw new Error(`Machine learning request '${JSON.stringify(config)}' failed for all URLs`);
  }

  async detectFaces(imagePath: string, { modelName, minScore }: FaceDetectionOptions) {
    const request = {
      [ModelTask.FACIAL_RECOGNITION]: {
        [ModelType.DETECTION]: { modelName, options: { minScore } },
        [ModelType.RECOGNITION]: { modelName },
      },

View on GitHub (pinned to e55ac299a4)