{"record":{"id":"c08c143b987a6723","repo":"datawhalechina/hello-agents","slug":"zip","errorCode":null,"errorMessage":"只接受 .zip 格式的压缩包","messagePattern":"只接受 \\.zip 格式的压缩包","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"Co-creation-projects/angelen-SoftwareDevHelper/src/main.py","lineNumber":200,"sourceCode":"            elif msg.role == \"tool\":\n                tool_call_id = getattr(msg, \"tool_call_id\", None)\n                if tool_call_id:\n                    for tc_info in tool_calls_info:\n                        if tc_info[\"id\"] == tool_call_id:\n                            tc_info[\"result\"] = msg.content\n                            break\n\n        # 保存助手消息（同时保存工具调用信息）\n        save_session_history(session_id, title, response, False, tool_calls=tool_calls_info)\n\n        return {\"response\": response, \"session_id\": session_id, \"tool_calls\": tool_calls_info}\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=str(e))\n\n@app.post(\"/api/upload_project\")\nasync def upload_project(session_id: str = Form(...), file: UploadFile = File(...)):\n    if not file.filename.endswith('.zip'):\n        raise HTTPException(status_code=400, detail=\"只接受 .zip 格式的压缩包\")\n\n    upload_dir = os.path.join(os.path.dirname(__file__), \"../outputs/uploads\")\n    os.makedirs(upload_dir, exist_ok=True)\n    \n    file_id = str(uuid.uuid4())\n    file_path = os.path.join(upload_dir, f\"{file_id}_{file.filename}\")\n    \n    try:\n        with open(file_path, \"wb\") as buffer:\n            shutil.copyfileobj(file.file, buffer)\n            \n        agent = get_or_create_agent(session_id)\n        \n        prompt = f\"用户上传了项目压缩包，路径为：{file_path}。请根据当前题目要求，编写 pytest 测试用例，并使用 code_test 工具进行测试打分，最后给出反馈并更新用户水平记录。\"\n\n        save_session_history(session_id, \"上传项目测试\", f\"[上传项目] {file.filename}\", True)\n\n        history_len_before = len(agent.get_history())","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/angelen-SoftwareDevHelper/src/main.py#L182-L218","documentation":"POST /api/upload_project rejects any upload whose filename does not end with the literal lowercase suffix '.zip', raising HTTPException 400 with the Chinese message 'only .zip archives are accepted'. It is an input-format validation guard that runs before the file is written to `outputs/uploads`.","triggerScenarios":"Uploading .tar.gz, .rar, .7z, or a bare directory export; a filename like `Project.ZIP` or `Project.Zip` fails the case-sensitive endswith check; a client that sends no filename at all makes `file.filename` None and raises AttributeError inside the check instead.","commonSituations":"macOS/Windows users exporting projects as .zip but renamed with uppercase extensions; users trying to upload compressed formats the tool does not support; programmatic clients forgetting to set filename in multipart form-data.","solutions":["Re-package the project as a genuine .zip (e.g. `zip -r project.zip project/`) and re-upload.","If the extension is uppercase (`.ZIP`), the check still fails — rename to lowercase `.zip`.","Client-side: set the multipart filename explicitly (`file=@project.zip`) so `file.filename` is populated.","Server-side fix: `if not file.filename or not file.filename.lower().endswith('.zip')`."],"exampleFix":"// before\nif not file.filename.endswith('.zip'):\n    raise HTTPException(status_code=400, detail=\"只接受 .zip 格式的压缩包\")\n\n# after\nif not file.filename or not file.filename.lower().endswith('.zip'):\n    raise HTTPException(status_code=400, detail=\"只接受 .zip 格式的压缩包\")","handlingStrategy":"validation","validationCode":"import os\n\ndef can_upload(filename: str | None) -> bool:\n    return bool(filename) and filename.lower().endswith(\".zip\")\n\n# before POSTing\nassert can_upload(local_path.rsplit('/', 1)[-1]), \"must be a lowercase .zip\"","typeGuard":null,"tryCatchPattern":"try:\n    resp = client.post(\"/api/upload_project\", data={\"session_id\": sid}, files={\"file\": f})\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 400:\n        print(\"Repackage as .zip and retry\")\n    raise","preventionTips":["Always create archives with `zip -r project.zip dir/` so the extension is lowercase .zip.","Set the multipart filename explicitly in clients (curl -F 'file=@project.zip').","Validate the extension client-side before starting the upload to save bandwidth."],"tags":["fastapi","validation","file-upload","http-400","python"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}