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
- Rename the file client-side to a short, plain basename (letters, digits, dash, underscore, one allowed audio extension).
- Strip control characters and the internal prefix before upload if you generate names programmatically.
- 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
- Generate upload names from a strict allowlist alphabet (\w, dash, dot).
- Cap names at 200-odd chars to leave room for the extension.
- Never echo internal server temp-prefix patterns into user filenames.
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
- {request_id}: invalid filename
- {request_id}: {str(exc)}
- unsupported background music format; supported formats: {sup
- uploaded file must contain a decodable audio stream
- background music upload is not seekable
AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14).
Data as JSON: /api/errors/df6dcd1e90196c55.
Report an issue: GitHub.