harry0703/MoneyPrinterTurbo · error · BgmUploadError

unsupported background music format; supported formats: {sup

Error message

unsupported background music format; supported formats: {supported_formats}

What it means

Raised by sanitize_upload_filename when Path(safe_name).suffix.lower() is not in SUPPORTED_BGM_EXTENSIONS. The message lists the accepted formats (uppercased, dot-stripped) so the caller can self-correct. This is a cheap extension-level gate before the more expensive FFmpeg decode validation; content correctness is checked later by _validate_audio.

Source

Thrown at app/services/bgm.py:114

        or len(safe_name) > 255
        or any(ord(character) < 32 for character in safe_name)
        or any(character in _WINDOWS_INVALID_FILENAME_CHARS for character in safe_name)
        or safe_name.lower().startswith(_INTERNAL_UPLOAD_PREFIX)
    ):
        raise BgmUploadError("invalid background music filename")

    # Windows 会把扩展名前的首段识别为设备名,例如 CON.mp3、LPT1.wav 都
    # 不能作为普通文件创建。即使服务端最终使用 UUID,提前拒绝这类名称也能
    # 保证 API 在不同平台上的输入行为一致。
    windows_basename = safe_name.split(".", 1)[0].rstrip(" .").upper()
    if windows_basename in _WINDOWS_RESERVED_FILENAMES:
        raise BgmUploadError("invalid background music filename")
    if Path(safe_name).suffix.lower() not in SUPPORTED_BGM_EXTENSIONS:
        supported_formats = ", ".join(
            extension.removeprefix(".").upper()
            for extension in SUPPORTED_BGM_EXTENSIONS
        )
        raise BgmUploadError(
            f"unsupported background music format; supported formats: {supported_formats}"
        )
    return safe_name


def _validate_audio(file_path: str, timeout_seconds: int = 30) -> None:
    """
    仅使用项目当前配置的 FFmpeg 验证文件包含可完整解码的音频流。

    项目允许 imageio-ffmpeg 提供便携 FFmpeg,该安装方式不保证同时存在
    FFprobe,因此不能新增独立二进制依赖。`-map 0:a:0` 会在没有音频流时失败,
    `-xerror` 会把解码错误提升为失败;完整解码还能拦截加密文件或随机数据偶然
    命中音频帧头的误判。文件可以包含专辑封面等附加流,但只校验第一条音频流。
    """
    try:
        decoded = subprocess.run(
            [
                utils.get_ffmpeg_binary(),

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Re-encode to one of the formats named in the error message (e.g. MP3/M4A/WAV) using ffmpeg or another transcoder.
  2. Verify the final suffix client-side: Path(name).suffix.lower() must be in the supported set — fix double extensions before upload.

Example fix

# before: wrong final extension
files = {"file": ("song.mp3.txt", open("song.mp3", "rb"))}

# after
files = {"file": ("song.mp3", open("song.mp3", "rb"))}
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
SUPPORTED = {".mp3", ".m4a", ".wav"}  # mirror SUPPORTED_BGM_EXTENSIONS
if Path(filename).suffix.lower() not in SUPPORTED:
    raise ValueError(f"unsupported format; use one of {sorted(SUPPORTED)}")

Type guard

def has_supported_audio_suffix(name: str, supported: frozenset[str]) -> bool:
    return Path((name or "").strip()).suffix.lower() in supported

Prevention

When it happens

Trigger: Uploading .wma, .ogg (if unsupported), .flac, or a mismatched double extension like 'song.mp3.txt' whose actual suffix is .txt; a file with no extension at all.

Common situations: Users with music in formats outside the supported set; clients preserving original store formats; renaming that leaves the wrong final extension.

Related errors


AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14). Data as JSON: /api/errors/c85d6a06a20bea65. Report an issue: GitHub.