{"record":{"id":"2cfbe3bc758cd2c6","repo":"sgl-project/sglang","slug":"generation-is-still-in-progress","errorCode":null,"errorMessage":"Generation is still in-progress","messagePattern":"Generation is still in-progress","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"python/sglang/multimodal_gen/runtime/entrypoints/openai/mesh_api.py","lineNumber":270,"sourceCode":"\n\n@router.get(\"/{mesh_id}/content\")\nasync def download_mesh_content(\n    mesh_id: str = Path(...), variant: Optional[str] = Query(None)\n):\n    job = await MESH_STORE.get(mesh_id)\n    if not job:\n        raise HTTPException(status_code=404, detail=\"Mesh not found\")\n\n    if job.get(\"url\"):\n        raise HTTPException(\n            status_code=400,\n            detail=f\"Mesh has been uploaded to cloud storage. Please use the cloud URL: {job.get('url')}\",\n        )\n\n    file_path = job.get(\"file_path\")\n    if not file_path or not os.path.exists(file_path):\n        raise HTTPException(status_code=404, detail=\"Generation is still in-progress\")\n\n    ext = os.path.splitext(file_path)[1].lower()\n    media_type = {\n        \".glb\": \"model/gltf-binary\",\n        \".obj\": \"text/plain\",\n    }.get(ext, \"application/octet-stream\")\n\n    return FileResponse(\n        path=file_path, media_type=media_type, filename=os.path.basename(file_path)\n    )\n","sourceCodeStart":252,"sourceCodeEnd":281,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/entrypoints/openai/mesh_api.py#L252-L281","documentation":"The mesh job exists but has no file_path yet (or the file was deleted from disk), so content download returns HTTP 404 'Generation is still in-progress'. The job record exists but the artifact file is not ready.","triggerScenarios":"Polling GET /{mesh_id}/content immediately after job creation, before generation finished and wrote the output file.","commonSituations":"Impatient polling without backoff; job failed before writing output; artifact cleaned from disk by a janitor process.","solutions":["Poll GET /{mesh_id} status until completed/failed before requesting content","Add exponential backoff between content-download attempts","Inspect job status: if it shows failed, re-submit instead of retrying download"],"exampleFix":"# before\nresp = await client.get(f\"/v1/mesh/{id}/content\")\n# after\nwhile (job := (await client.get(f\"/v1/mesh/{id}\")).json())[\"status\"] not in (\"completed\",\"failed\"):\n    await asyncio.sleep(2)\nresp = await client.get(f\"/v1/mesh/{id}/content\")","handlingStrategy":"retry","validationCode":"job = (await client.get(f'/v1/mesh/{id}')).json()\nif job['status'] != 'completed': sleep and re-poll","typeGuard":null,"tryCatchPattern":"while True:\n    r = await client.get(f'/v1/mesh/{id}/content')\n    if r.status_code != 404 or 'in-progress' not in r.text: break\n    await asyncio.sleep(2)","preventionTips":["Poll job status until terminal state before fetching content","Back off exponentially"],"tags":["http","async-job","polling","mesh-generation"],"backgroundTag":"job-not-ready","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}