{"record":{"id":"d6a876ffe6612af9","repo":"immich-app/immich","slug":"machine-learning-request-json-stringify-config","errorCode":null,"errorMessage":"Machine learning request '${JSON.stringify(config)}' failed for all URLs","messagePattern":"Machine learning request '(.+?)' failed for all URLs","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/repositories/machine-learning.repository.ts","lineNumber":187,"sourceCode":"    ]) {\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      },\n    };\n    const response = await this.predict<FacialRecognitionResponse>({ imagePath }, request);\n    return {\n      imageHeight: response.imageHeight,\n      imageWidth: response.imageWidth,\n      faces: response[ModelTask.FACIAL_RECOGNITION],\n    };\n  }\n\n  async encodeImage(imagePath: string, { modelName }: MachineLearningConfig['clip']) {","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/repositories/machine-learning.repository.ts#L169-L205","documentation":"The machine learning repository attempts the prediction request against each configured ML URL in order, logging a warning per failed URL. If every URL fails (connection refused, timeout, HTTP errors), it throws with the serialized request config, indicating the ML service is unreachable or unhealthy rather than a problem with the request itself.","triggerScenarios":"All entries in MACHINE_LEARNING_URLS are unreachable at request time: ML container down, wrong host/port, network policy blocking the call, or the ML service crashing on the request — after which the loop falls through to the final throw.","commonSituations":"ML container not started or crashed (OOM during model load); misconfigured MACHINE_LEARNING_URL (e.g. 127.0.0.1 when ML runs in another container); Docker network misconfiguration; ML model failing on a particular image so every attempt errors.","solutions":["Verify the ML service is up and reachable: curl http://machine-learning:3003/ping from the server container","Check/fix MACHINE_LEARNING_URL(S) env — it must match the ML container's host:port and Docker network","Inspect ML container logs for startup/model-load crashes and fix (e.g. increase memory, fix model name)","Ensure request payload matches the running ML server's supported schema/version (align Immich server and ML image versions)"],"exampleFix":"// before (docker-compose.yml, server env)\nMACHINE_LEARNING_URL=http://127.0.0.1:3003\n// after — use the compose service name\nMACHINE_LEARNING_URL=http://immich-machine-learning:3003","handlingStrategy":"retry","validationCode":"for (const url of mlUrls) {\n  try { const r = await fetch(`${url}/ping`); if (!r.ok) throw new Error(String(r.status)); }\n  catch { throw new Error(`ML service unreachable at ${url}; check container/network`); }\n}","typeGuard":"function mlUrlLooksValid(url: string): boolean {\n  try { const u = new URL(url); return u.protocol === 'http:' || u.protocol === 'https:'; } catch { return false; }\n}","tryCatchPattern":"try {\n  const result = await mlRepo.predict(url, config, input);\n} catch (e) {\n  if ((e as Error).message.includes('failed for all URLs')) {\n    logger.warn('ML unreachable; queueing for retry', { config });\n    await jobRepo.add({ name: JobName.X, data: input }); // retry via queue with backoff\n  } else throw e;\n}","preventionTips":["Health-check the ML /ping endpoint in readiness probes before serving traffic","Use compose service DNS names, not localhost, for cross-container ML URLs","Keep server and ML image versions aligned and monitor ML container logs/memory"],"tags":["network","machine-learning","request-failed","configuration"],"backgroundTag":"http-request-failed","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"}