{"record":{"id":"764e47cf5db7dd48","repo":"immich-app/immich","slug":"invalid-request-format","errorCode":null,"errorMessage":"Invalid request format.","messagePattern":"Invalid request format\\.","errorType":"http","errorClass":"HTTPException","httpStatus":422,"severity":"error","filePath":"machine-learning/immich_ml/main.py","lineNumber":150,"sourceCode":"def get_entries(entries: str = Form()) -> InferenceEntries:\n    try:\n        request: PipelineRequest = orjson.loads(entries)\n        without_deps: list[InferenceEntry] = []\n        with_deps: list[InferenceEntry] = []\n        for task, types in request.items():\n            for type, entry in types.items():\n                parsed: InferenceEntry = {\n                    \"name\": entry[\"modelName\"],\n                    \"task\": task,\n                    \"type\": type,\n                    \"options\": entry.get(\"options\", {}),\n                }\n                dep = get_model_deps(parsed[\"name\"], type, task)\n                (with_deps if dep else without_deps).append(parsed)\n        return without_deps, with_deps\n    except (orjson.JSONDecodeError, ValidationError, KeyError, AttributeError) as e:\n        log.error(f\"Invalid request format: {e}\")\n        raise HTTPException(422, \"Invalid request format.\")\n\n\napp = FastAPI(lifespan=lifespan)\n\n\n@app.get(\"/\")\nasync def root() -> ORJSONResponse:\n    return ORJSONResponse({\"message\": \"Immich ML\"})\n\n\n@app.get(\"/ping\")\ndef ping() -> PlainTextResponse:\n    return PlainTextResponse(\"pong\")\n\n\n@app.post(\"/predict\", dependencies=[Depends(update_state)])\nasync def predict(\n    entries: InferenceEntries = Depends(get_entries),","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/machine-learning/immich_ml/main.py#L132-L168","documentation":"Raised as FastAPI HTTPException(422) by get_entries in machine-learning/immich_ml/main.py when parsing the 'entries' form field into a PipelineRequest fails. It catches orjson.JSONDecodeError, pydantic ValidationError, KeyError, and AttributeError — i.e. malformed JSON, missing modelName, or wrong request structure — and converts them into a uniform 422.","triggerScenarios":"POST /predict with an 'entries' field that is not valid JSON, is missing the required 'modelName' key inside a type entry, or has a structure that does not match the {task: {type: {modelName, options}}} shape.","commonSituations":"Immich server and ML service version mismatch producing a different pipeline schema; a custom/old client sending the previous request format; truncated request body; manual curl with a malformed --form string.","solutions":["Ensure the Immich server and machine-learning container are on the same release version.","Validate the entries JSON shape: top-level object keyed by task, each value keyed by type, each entry containing 'modelName'.","If calling manually, build entries with orjson/json.dumps from a typed dict rather than hand-written JSON."],"exampleFix":"# before\ncurl -F 'entries={\"visual\": {\"search\": {}}}' ...   # missing modelName\n\n# after\nentries = {\"visual\": {\"search\": {\"modelName\": \"ViT-B-32__openai\"}}}\ncurl -F 'entries=<echo $entries' ...","handlingStrategy":"validation","validationCode":"import orjson, jsonschema\nraw = orjson.loads(entries_text)\n# check the {task: {type: {modelName}}} structure\nfor task, types in raw.items():\n    for type_, entry in types.items():\n        assert 'modelName' in entry, f'missing modelName for {task}/{type_}'","typeGuard":"def is_pipeline_request(v) -> bool:\n    if not isinstance(v, dict): return False\n    for types in v.values():\n        if not isinstance(types, dict): return False\n        for entry in types.values():\n            if not isinstance(entry, dict) or 'modelName' not in entry: return False\n    return True","tryCatchPattern":"try:\n    entries = json.loads(raw)\nexcept (json.JSONDecodeError, KeyError) as e:\n    raise HTTPException(422, 'Invalid request format.')","preventionTips":["Build the entries payload with a typed pydantic model, not hand-written JSON.","Keep the Immich server and ML service on the same version."],"tags":["machine-learning","fastapi","request-validation","predict","json"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}