{"record":{"id":"ae3342139d5d90b2","repo":"immich-app/immich","slug":"machine-learning-request-to-url-failed-with-status-response","errorCode":null,"errorMessage":"Machine learning request to \"${url}\" failed with status ${response.status}: ${response.statusText}","messagePattern":"Machine learning request to \"(.+?)\" failed with status (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/src/repositories/machine-learning.repository.ts","lineNumber":177,"sourceCode":"    return this.healthyMap[url];\n  }\n\n  private async predict<T>(payload: ModelPayload, config: MachineLearningRequest): Promise<T> {\n    const formData = await this.getFormData(payload, config);\n\n    for (const url of [\n      // try healthy servers first\n      ...this.config.urls.filter((url) => this.isHealthy(url)),\n      ...this.config.urls.filter((url) => !this.isHealthy(url)),\n    ]) {\n      try {\n        const response = await fetch(new URL('predict', url), { method: 'POST', body: formData });\n        if (response.ok) {\n          this.setHealthy(url, true);\n          return response.json();\n        }\n\n        this.logger.warn(\n          `Machine learning request to \"${url}\" failed with status ${response.status}: ${response.statusText}`,\n        );\n      } catch (error: Error | unknown) {\n        this.logger.warn(`Machine learning request to \"${url}\" failed`, error);\n      }\n\n      this.setHealthy(url, false);\n    }\n\n    throw new Error(`Machine learning request '${JSON.stringify(config)}' failed for all URLs`);\n  }\n\n  async detectFaces(imagePath: string, { modelName, minScore }: FaceDetectionOptions) {\n    const request = {\n      [ModelTask.FACIAL_RECOGNITION]: {\n        [ModelType.DETECTION]: { modelName, options: { minScore } },\n        [ModelType.RECOGNITION]: { modelName },\n      },","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/repositories/machine-learning.repository.ts#L159-L195","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the machine-learning container logs for the stack trace corresponding to the logged status.","Verify IMMICH_MACHINE_LEARNING_URL points to the correct reachable host:port of the ML service.","Restart the machine-learning container; increase its memory limit if it was OOM-killed.","Ensure server and machine-learning images are the same version.","If status 413/4xx, lower concurrency or image size settings for ML jobs."],"exampleFix":"// before\nconst response = await fetch(new URL('predict', url), { method: 'POST', body: formData });\n// after (add timeout + explicit status logging)\nconst response = await fetch(new URL('predict', url), { method: 'POST', body: formData, signal: AbortSignal.timeout(30_000) });\nif (!response.ok) this.logger.warn(`ML predict failed: ${response.status} ${await response.text()}`);","handlingStrategy":"retry","validationCode":"const health = await fetch(new URL('ping', mlUrl)).then(r => r.ok, () => false);\nif (!health) throw new Error(`ML server ${mlUrl} not ready`);","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(new URL('predict', url), { method: 'POST', body: formData, signal: AbortSignal.timeout(30_000) });\n  if (!res.ok) throw new Error(`ML ${res.status}: ${res.statusText}`);\n  return await res.json();\n} catch (e) {\n  logger.warn(`ML predict failed, using fallback`, e);\n  return null; // degrade: skip smart-search/face features\n}","preventionTips":["Health-check the ML container before running bulk jobs.","Pin matching server/ML image versions.","Give the ML container ample memory (model loading OOM is common).","Add a fetch timeout and bounded retries with backoff."],"tags":["network","http","machine-learning","microservice"],"backgroundTag":"http-error-response","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"}