datawhalechina/hello-agents · warning · HTTPException
只接受 .zip 格式的压缩包
Error message
只接受 .zip 格式的压缩包
What it means
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`.
Source
Thrown at Co-creation-projects/angelen-SoftwareDevHelper/src/main.py:200
elif msg.role == "tool":
tool_call_id = getattr(msg, "tool_call_id", None)
if tool_call_id:
for tc_info in tool_calls_info:
if tc_info["id"] == tool_call_id:
tc_info["result"] = msg.content
break
# 保存助手消息(同时保存工具调用信息)
save_session_history(session_id, title, response, False, tool_calls=tool_calls_info)
return {"response": response, "session_id": session_id, "tool_calls": tool_calls_info}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/api/upload_project")
async def upload_project(session_id: str = Form(...), file: UploadFile = File(...)):
if not file.filename.endswith('.zip'):
raise HTTPException(status_code=400, detail="只接受 .zip 格式的压缩包")
upload_dir = os.path.join(os.path.dirname(__file__), "../outputs/uploads")
os.makedirs(upload_dir, exist_ok=True)
file_id = str(uuid.uuid4())
file_path = os.path.join(upload_dir, f"{file_id}_{file.filename}")
try:
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
agent = get_or_create_agent(session_id)
prompt = f"用户上传了项目压缩包,路径为:{file_path}。请根据当前题目要求,编写 pytest 测试用例,并使用 code_test 工具进行测试打分,最后给出反馈并更新用户水平记录。"
save_session_history(session_id, "上传项目测试", f"[上传项目] {file.filename}", True)
history_len_before = len(agent.get_history())View on GitHub (pinned to 606a07d341)
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')`.
Example fix
// before
if not file.filename.endswith('.zip'):
raise HTTPException(status_code=400, detail="只接受 .zip 格式的压缩包")
# after
if not file.filename or not file.filename.lower().endswith('.zip'):
raise HTTPException(status_code=400, detail="只接受 .zip 格式的压缩包") Defensive patterns
Strategy: validation
Validate before calling
import os
def can_upload(filename: str | None) -> bool:
return bool(filename) and filename.lower().endswith(".zip")
# before POSTing
assert can_upload(local_path.rsplit('/', 1)[-1]), "must be a lowercase .zip" Try / catch
try:
resp = client.post("/api/upload_project", data={"session_id": sid}, files={"file": f})
except httpx.HTTPStatusError as e:
if e.response.status_code == 400:
print("Repackage as .zip and retry")
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/c08c143b987a6723.
Report an issue: GitHub.