{"record":{"id":"64f014dbd3a45b5f","repo":"sgl-project/sglang","slug":"invalid-request-body-e-64f014","errorCode":null,"errorMessage":"Invalid request body: {e}","messagePattern":"Invalid request body: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/entrypoints/openai/video_api.py","lineNumber":816,"sourceCode":"            if payload.get(\"reference_url\") and not _is_probably_video_source(\n                payload.get(\"reference_url\")\n            ):\n                try:\n                    input_path = await _save_first_input_image(\n                        payload.get(\"reference_url\"),\n                        request_id,\n                        uploads_dir,\n                        prefer_remote_source=server_args.input_save_path is None,\n                    )\n                except Exception as e:\n                    raise HTTPException(\n                        status_code=400,\n                        detail=f\"Failed to process image source: {str(e)}\",\n                    )\n                payload[\"input_reference\"] = input_path\n            req = VideoGenerationsRequest(**payload)\n        except Exception as e:\n            raise HTTPException(status_code=400, detail=f\"Invalid request body: {e}\")\n\n    # Resolve per-request output_path override\n    effective_output_path = req.output_path or server_args.output_path\n    if effective_output_path is None:\n        output_tmp = tempfile.mkdtemp(prefix=\"sglang_output_\")\n        temp_dirs.append(output_tmp)\n        effective_output_path = output_tmp\n        output_persistent = False\n\n    # Inject resolved output_path so _build_video_sampling_params picks it up\n    req.output_path = effective_output_path\n\n    logger.debug(f\"Server received from create_video endpoint: req={req}\")\n\n    try:\n        sampling_params = _build_video_sampling_params(request_id, req)\n    except (ValueError, TypeError) as e:\n        for td in temp_dirs:","sourceCodeStart":798,"sourceCodeEnd":834,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/entrypoints/openai/video_api.py#L798-L834","documentation":"Raised by the SGLang video generation OpenAI-compatible endpoint when the JSON request body cannot be parsed or fails validation into a VideoGenerationsRequest. Any exception while decoding the body, resolving an input image reference, or constructing the Pydantic request model is re-raised as an HTTP 400 with the underlying message. It is a client-side validation error, not a server fault.","triggerScenarios":"POST /v1/videos with malformed JSON, missing required fields (e.g. model or prompt), wrong types for fields like size/duration, an unparsable input_reference payload, or an image source that fails processing so VideoGenerationsRequest(**payload) or the earlier body-parsing step throws.","commonSituations":"Cutting-and-pasting curl/JS examples from a different API version where field names changed; sending base64 image data with an unsupported format; omitting newly-required fields after upgrading SGLang; sending null for a required field.","solutions":["Validate the payload against the VideoGenerationsRequest schema before sending (required fields: model, prompt; check types for size/duration/input_reference)","Inspect the detail string — it embeds the original Pydantic/validation error which names the offending field","If using input_reference images, verify the image source is a valid URL/base64/data path","Check the server logs for the full exception traceback if the detail message is truncated"],"exampleFix":"// before\ncurl -X POST http://localhost:30000/v1/videos -d '{\"model\": \"video-model\", \"prompt\": null}'\n// after\ncurl -X POST http://localhost:30000/v1/videos -H 'Content-Type: application/json' -d '{\"model\": \"video-model\", \"prompt\": \"a cat surfing\"}'","handlingStrategy":"validation","validationCode":"import json\nrequired = {\"model\", \"prompt\"}\nbody = {...}\nassert required <= set(body), f'missing: {required - set(body)}'\nassert isinstance(body[\"prompt\"], str) and body[\"prompt\"]\njson.dumps(body)  # serializable & valid JSON","typeGuard":"function isVideoRequestBody(b: unknown): b is VideoGenerationsRequest {\n  const o = b as any;\n  return !!o && typeof o.model === 'string' && typeof o.prompt === 'string' && o.prompt.length > 0;\n}","tryCatchPattern":"try { await client.post('/v1/videos', body); } catch (e) { if (e.status === 400) throw new Error(`Bad video request: ${e.detail}`); throw e; }","preventionTips":["Schema-validate payloads client-side against VideoGenerationsRequest before sending","Send Content-Type: application/json explicitly","Keep client field names in sync with the server version's request model"],"tags":["http-400","request-validation","video-generation","openai-api"],"backgroundTag":"request-body-validation-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}