harry0703/MoneyPrinterTurbo · error · BgmUploadError
background music file is empty
Error message
background music file is empty
What it means
Raised after the copy loop in stage_bgm_upload when total_bytes == 0, i.e. the uploaded source produced an EOF on the very first read. The temp file was created and fsynced but no content was written, so it is removed and BgmUploadError('background music file is empty') is raised. This rejects zero-byte uploads before FFmpeg validation ever runs.
Source
Thrown at app/services/bgm.py:213
suffix=Path(safe_name).suffix.lower(),
dir=target_dir,
)
with os.fdopen(descriptor, "wb") as output:
while True:
chunk = source.read(_COPY_CHUNK_BYTES)
if not chunk:
break
if not isinstance(chunk, (bytes, bytearray, memoryview)):
raise BgmUploadError("background music upload must be binary")
total_bytes += len(chunk)
if total_bytes > MAX_BGM_UPLOAD_BYTES:
raise BgmUploadError("background music file exceeds the 30 MB limit")
output.write(chunk)
output.flush()
os.fsync(output.fileno())
if total_bytes == 0:
raise BgmUploadError("background music file is empty")
return safe_name, temp_path, total_bytes
except Exception as exc:
_remove_staged_file(temp_path)
if isinstance(exc, BgmUploadError):
raise
if isinstance(exc, OSError):
raise BgmServiceError("failed to stage background music upload") from exc
raise
finally:
# Streamlit 还需要使用同一个 UploadedFile 做浏览器试听;恢复文件指针可
# 避免校验后播放器或最终保存读取到空内容。
try:
source.seek(0)
except (AttributeError, OSError):
pass
def validate_bgm_upload(filename: str, source: BinaryIO) -> str:View on GitHub (pinned to 1f9f19c202)
Solutions
- Check the file size before calling the API (seek to end / os.fstat) and reject or skip empty files client-side.
- If the file object was previously read, call source.seek(0) before staging.
- Verify the upload is not a placeholder/dummy file created by the frontend on failure.
Example fix
// before
source.seek(0) # missing -> EOF immediately
safe_name, temp_path, size = stage_bgm_upload(source, name)
// after
source.seek(0)
if isinstance(source, (io.RawIOBase, io.BufferedIOBase)) and not source.read(1):
raise ValueError('empty upload')
source.seek(0)
safe_name, temp_path, size = stage_bgm_upload(source, name) Defensive patterns
Strategy: validation
Validate before calling
fh.seek(0, os.SEEK_END)
size = fh.tell()
fh.seek(0)
if size == 0:
raise ClientError('empty file') Try / catch
try:
stage_bgm_upload(fh, filename)
except BgmUploadError as e:
if 'is empty' in str(e):
show_user('The selected file is empty; re-export the audio') Prevention
- seek(0) any file object that was previously read before handing it to staging.
- Reject 0-byte files at the form/upload boundary.
- Remember staging restores the pointer in finally, but other readers may not — always reset before reuse.
When it happens
Trigger: Submitting an empty (0-byte) file to the BGM upload endpoint, or a file-like object already at EOF because a previous validation pass consumed it without seeking back to 0.
Common situations: Front-end bug sending an empty FormData part; the same UploadedFile read twice without seek(0) — note stage_bgm_upload itself restores the pointer in finally, but other code that reads first may not; truncated uploads from flaky networks.
Related errors
- uploaded file must contain a decodable audio stream
- background music file exceeds the 30 MB limit
- {request_id}: {str(exc)}
- invalid background music filename
- unsupported background music format; supported formats: {sup
AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14).
Data as JSON: /api/errors/0d9bb57297242b54.
Report an issue: GitHub.