harry0703/MoneyPrinterTurbo · error · HttpException
{request_id}: invalid filename
Error message
{request_id}: invalid filename What it means
Raised by _sanitize_upload_filename in app/controllers/v1/video.py when an uploaded file's name, after stripping any directory components (both / and \ separators), is empty or is exactly '.' or '..'. The sanitization exists because browsers and clients sometimes attach directory information or ../ traversal fragments, and this guard keeps uploads inside the target directory. It maps to HTTP 400 with '{request_id}: invalid filename'.
Source
Thrown at app/controllers/v1/video.py:70
if _enable_redis:
task_manager = RedisTaskManager(
max_concurrent_tasks=_max_concurrent_tasks,
redis_url=redis_url,
max_queued_tasks=_max_queued_tasks,
)
else:
task_manager = InMemoryTaskManager(
max_concurrent_tasks=_max_concurrent_tasks,
max_queued_tasks=_max_queued_tasks,
)
def _sanitize_upload_filename(filename: str, request_id: str) -> str:
# 浏览器或客户端有时会附带目录信息,甚至可能夹带 ../ 这类穿越片段。
# 这里只保留纯文件名,避免上传接口把文件写到目标目录之外。
normalized_name = (filename or "").replace("\\", "/").split("/")[-1].strip()
if not normalized_name or normalized_name in {".", ".."}:
raise HttpException(
task_id=request_id,
status_code=400,
message=f"{request_id}: invalid filename",
)
return normalized_name
def _resolve_path_within_directory(base_dir: str, unsafe_path: str, request_id: str) -> str:
try:
return file_security.resolve_path_within_directory(base_dir, unsafe_path)
except ValueError as exc:
logger.warning(
f"reject unsafe file path, request_id: {request_id}, path: {unsafe_path}, "
f"error: {str(exc)}"
)
raise HttpException(
task_id=request_id,
status_code=404 if str(exc) == "file does not exist" else 403,View on GitHub (pinned to 1f9f19c202)
Solutions
- Set an explicit, sane basename on the upload, e.g. os.path.basename(path) or Path(path).name on the client side.
- Reject/repair filenames before upload: strip whitespace and refuse empty values.
- If building multipart bodies manually, always include a filename= value in the Content-Disposition part.
Example fix
# before
files = {"file": (user_supplied_path_or_empty, fh)}
requests.post(url, files=files, headers=h)
# after
from pathlib import Path
name = Path(user_supplied_path or "").name.strip()
if not name or name in {".", ".."}:
raise ValueError("invalid upload filename")
files = {"file": (name, fh)}
requests.post(url, files=files, headers=h) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
name = Path(filename or "").name.strip()
if not name or name in {".", ".."}:
raise ValueError("upload filename is empty or a directory reference") Type guard
def is_safe_upload_filename(filename: str | None) -> bool:
n = (filename or "").replace("\\", "/").split("/")[-1].strip()
return bool(n) and n not in {".", ".."} Try / catch
try:
resp = requests.post(url, files={"file": (name, fh)}, headers=h)
except requests.HTTPError as e:
if e.response.status_code == 400 and "invalid filename" in e.response.text:
name = Path(name).name or "upload.bin" # repair and let caller re-ask user
raise Prevention
- Always derive the upload name with os.path.basename/Path(...).name on the client.
- Reject empty filenames in the UI before the request is built.
- When constructing multipart bodies manually, always include filename= in Content-Disposition.
When it happens
Trigger: Uploading a file whose filename is an empty string, '/', '.', '..', or only whitespace/backslashes; a multipart form built by hand that omits the filename parameter; a client sending a full Windows path that reduces to '..' after splitting.
Common situations: Programmatic uploads where the client passes a path variable instead of a basename; tests using placeholder filenames like '.'; HTTP libraries that default filename to '' when given None.
Related errors
- {request_id}: {str(exc)}
- {request_id}: Only files with extensions {', '.join(allowed_
- invalid background music filename
- {request_id}: invalid file path
- unsupported background music format; supported formats: {sup
AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14).
Data as JSON: /api/errors/e20073fd003a24a7.
Report an issue: GitHub.