{"record":{"id":"9353950e545dd14a","repo":"bytedance/deer-flow","slug":"too-many-files-maximum-is-limits-max-files","errorCode":null,"errorMessage":"Too many files: maximum is {limits.max_files}","messagePattern":"Too many files: maximum is (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":413,"severity":"warning","filePath":"backend/app/gateway/routers/uploads.py","lineNumber":314,"sourceCode":"    except Exception:\n        return False\n\n\n@router.post(\"\", response_model=UploadResponse)\n@require_permission(\"threads\", \"write\", owner_check=True, require_existing=False)\nasync def upload_files(\n    thread_id: ThreadId,\n    request: Request,\n    files: list[UploadFile] = File(...),\n    config: AppConfig = Depends(get_config),\n) -> UploadResponse:\n    \"\"\"Upload multiple files to a thread's uploads directory.\"\"\"\n    if not files:\n        raise HTTPException(status_code=400, detail=\"No files provided\")\n\n    limits = _get_upload_limits(config)\n    if len(files) > limits.max_files:\n        raise HTTPException(status_code=413, detail=f\"Too many files: maximum is {limits.max_files}\")\n\n    try:\n        effective_user_id = get_effective_user_id()\n        uploads_dir = await run_file_io(ensure_uploads_dir, thread_id, user_id=effective_user_id)\n    except ValueError as e:\n        raise HTTPException(status_code=400, detail=str(e))\n    sandbox_uploads = uploads_dir\n    uploaded_files = []\n    written_paths = []\n    sandbox_sync_targets = []\n    skipped_files = []\n    total_size = 0\n    # Track filenames within this request so duplicate form parts do not\n    # silently truncate each other. Existing uploads keep the historical\n    # overwrite behavior for a single replacement upload.\n    seen_filenames: set[str] = set()\n\n    sandbox_provider = get_sandbox_provider()","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/uploads.py#L296-L332","documentation":"Raised by the multi-file upload endpoint when the number of files in a single multipart request exceeds the configured limit (limits.max_files from the gateway's upload limits config). The endpoint counts form file parts before writing anything and rejects the whole request with HTTP 413 so no partial uploads occur. It exists to bound request handling cost per call.","triggerScenarios":"POST multipart/form-data to /threads/{thread_id}/uploads with more `files` parts than config.max_files (default set by the gateway's upload limits). E.g. attaching 11 files when max_files is 10.","commonSituations":"Bulk-attaching many documents in a chat UI; lowering max_files in config.yaml after clients were already batching large uploads; automated scripts that glob a directory and upload everything at once.","solutions":["Split the upload into batches of at most limits.max_files files per request.","Check GET /threads/{thread_id}/uploads/limits (the endpoint that returns _get_upload_limits) before uploading and chunk accordingly.","If the use case legitimately needs more files per call, raise the max_files upload limit in the gateway config and restart."],"exampleFix":"// before\nconst form = new FormData();\nallFiles.forEach(f => form.append('files', f));\nawait fetch(`/api/threads/${tid}/uploads`, {method:'POST', body: form});\n\n// after\nconst limits = await fetch(`/api/threads/${tid}/uploads/limits`).then(r=>r.json());\nfor (const batch of chunk(allFiles, limits.max_files)) {\n  const form = new FormData();\n  batch.forEach(f => form.append('files', f));\n  await fetch(`/api/threads/${tid}/uploads`, {method:'POST', body: form});\n}","handlingStrategy":"validation","validationCode":"const limits = await fetch(`/api/threads/${tid}/uploads/limits`).then(r => r.json());\nconst batches = chunk(files, limits.max_files);\n// upload batches sequentially","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Fetch upload limits before building the multipart request and chunk client-side.","Set the batching size from the limits endpoint, never hardcode it.","Raise max_files in gateway config only when the workflow genuinely requires larger batches."],"tags":["upload","http-413","validation","gateway"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}