harry0703/MoneyPrinterTurbo · error · HttpException
{request_id}: {str(exc)}
Error message
{request_id}: {str(exc)} What it means
Raised by the POST BGM upload endpoint when bgm_service.save_bgm_upload raises BgmUploadError. This error class covers user-attributable problems: invalid or reserved filenames, unsupported extension, undecodable audio stream, non-seekable upload stream, or an empty file. The endpoint maps it to 400 with str(exc) embedded, logging request_id and reason at warning level without dumping file contents or absolute paths.
Source
Thrown at app/controllers/v1/video.py:353
"Validate an MP3, M4A, AAC, WAV, FLAC, OGG, OPUS, or WMA file up to "
"30 MB and store it under an immutable UUID filename in storage/bgm."
),
responses={
400: {"description": "The filename, format, size, or audio stream is invalid"},
500: {"description": "FFmpeg validation or persistent storage is unavailable"},
},
)
def upload_bgm_file(request: Request, file: UploadFile = File(...)):
request_id = base.get_task_id(request)
try:
safe_filename = bgm_service.save_bgm_upload(file.filename, file.file)
except bgm_service.BgmUploadError as exc:
# 上传失败通常可以由用户更换文件后恢复,因此记录 request_id 和明确原因,
# 但不输出文件内容或绝对路径,避免日志泄露用户数据。
logger.warning(
f"background music upload rejected: request_id={request_id}, error={str(exc)}"
)
raise HttpException(
task_id=request_id,
status_code=400,
message=f"{request_id}: {str(exc)}",
)
except bgm_service.BgmServiceError as exc:
# 工具链或存储故障属于服务端问题,不能伪装成用户文件错误。日志保留
# request_id 和内部原因,HTTP 响应只返回稳定文案,避免暴露服务器路径。
logger.error(
f"background music upload failed: request_id={request_id}, error={str(exc)}"
)
raise HttpException(
task_id=request_id,
status_code=500,
message=f"{request_id}: background music validation is unavailable",
)
response = {"file": safe_filename}
return utils.get_response(200, response)View on GitHub (pinned to 1f9f19c202)
Solutions
- Read the 400 body: str(exc) names the exact sub-cause (invalid filename / unsupported format / no decodable audio / etc.) and fix that specific condition.
- Re-export the audio to a mainstream format (MP3/M4A/WAV per SUPPORTED_BGM_EXTENSIONS) with ffmpeg before uploading.
- Use a plain basename filename free of Windows-reserved stems and control characters.
- For streams, ensure the file object is seekable (read the upload into BytesIO first).
Example fix
# before
files = {"file": ("CON.mp3", open("song.mp3", "rb"))}
# after
files = {"file": ("my-song.mp3", open("song.mp3", "rb"))} Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path
suffix = Path(filename).suffix.lower()
if suffix not in SUPPORTED: # mirror the server's supported extension set
raise ValueError(f"convert to a supported format first: {sorted(SUPPORTED)}") Type guard
import re
RESERVED = {"CON","PRN","AUX","NUL",*(f"COM{i}" for i in range(1,10)),*(f"LPT{i}" for i in range(1,10))}
def is_valid_bgm_filename(name: str) -> bool:
n = (name or "").replace("\\", "/").split("/")[-1].strip()
return (
bool(n) and n not in {".", ".."} and len(n) <= 255
and all(ord(c) >= 32 for c in n)
and n.split(".", 1)[0].rstrip(" .").upper() not in RESERVED
and Path(n).suffix.lower() in SUPPORTED
) Try / catch
try:
resp = requests.post(bgm_url, files={"file": (name, fh)}, headers=h)
resp.raise_for_status()
except requests.HTTPError as e:
if e.response.status_code == 400:
detail = e.response.json()["message"] # embedded reason from BgmUploadError
prompt_user_to_fix_file(detail)
else:
raise # 500 = server-side BgmServiceError, not a user fix Prevention
- Pre-check filename, extension, and local FFmpeg decodability before uploading.
- Prefer mainstream formats (MP3/M4A/WAV) for uploads.
- Treat 400 as fixable-by-user and 500 as an ops problem; don't mix the handling.
When it happens
Trigger: POST /api/v1/bgm (background music upload) with: filename CON.mp3 or NUL.wav (Windows reserved); extension .wma when unsupported; a text file renamed to .mp3 (FFmpeg decode fails); an empty upload; a SpooledTemporaryFile-backed stream lacking seek().
Common situations: Users uploading music bought in DRM'd or exotic formats; clients sending OS-generated names; a frontend uploading before the File object is fully materialized; names colliding with the server's internal upload prefix.
Related errors
- {request_id}: invalid filename
- {request_id}: Only files with extensions {', '.join(allowed_
- invalid background music filename
- unsupported background music format; supported formats: {sup
- uploaded file must contain a decodable audio stream
AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14).
Data as JSON: /api/errors/b614ed09c7119e1d.
Report an issue: GitHub.