harry0703/MoneyPrinterTurbo · error · BgmUploadError

invalid background music filename

Error message

invalid background music filename

What it means

Raised by sanitize_upload_filename in app/services/bgm.py when the extracted basename fails basic hygiene: empty, '.'/'..', longer than 255 chars, contains control characters (ord < 32), contains Windows-invalid filename characters, or starts with the server's internal upload prefix (_INTERNAL_UPLOAD_PREFIX, reserved for temp files the service itself creates). All these make the name unsafe or ambiguous to persist cross-platform, so it is rejected before any bytes are written.

Source

Thrown at app/services/bgm.py:101

        # 等更准确的原始异常覆盖掉,但必须留下路径和系统错误供运维定位。
        logger.warning(
            f"failed to remove staged background music: path={file_path}, "
            f"error={str(exc)}"
        )


def sanitize_upload_filename(filename: str) -> str:
    """提取可跨平台展示的音频文件名,并拒绝非法名称与不支持的扩展名。"""
    safe_name = (filename or "").replace("\\", "/").split("/")[-1].strip()
    if (
        not safe_name
        or safe_name in {".", ".."}
        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

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Rename the file client-side to a short, plain basename (letters, digits, dash, underscore, one allowed audio extension).
  2. Strip control characters and the internal prefix before upload if you generate names programmatically.
  3. Cap generated names to <255 characters including extension.

Example fix

# before
name = track_title + ".mp3"   # could be 300 chars or contain '*/:<>?' chars

# after
import re
name = re.sub(r"[^\w\-. ]", "", track_title)[:200].strip() or "audio"
name += ".mp3"
Defensive patterns

Strategy: validation

Validate before calling

import re
name = (filename or "").replace("\\", "/").split("/")[-1].strip()
if (not name or name in {".", ".."} or len(name) > 255
        or any(ord(c) < 32 for c in name)
        or re.search(r'[<>:"/\\|?*]', name)):
    raise ValueError("filename fails server hygiene rules")

Type guard

def is_hygienic_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)
    )

Prevention

When it happens

Trigger: Uploading with filename 'aux?.mp3' (invalid char), a >255-char name, a name with embedded \0 or other control chars, or one beginning with the internal prefix (e.g. '.bgm-tmp-...' style) that could collide with staged temp files.

Common situations: Metadata-rich auto-generated names (track titles) exceeding length limits; filenames copied from Windows with trailing spaces/invalid chars; adversarial or fuzzed upload attempts probing the temp-file namespace.

Related errors


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