harry0703/MoneyPrinterTurbo · error · BgmUploadError

background music file is empty or missing

Error message

background music file is empty or missing

What it means

Raised by validate_audio_file in app/services/bgm.py as a pre-check before invoking FFmpeg: the path either is not a regular file or has size <= 0 on disk. This guards the reusable validation entry point (used for both upload preflight with a 30s timeout and validating Sonilo-generated tracks up to 6 minutes with a 120s timeout) so FFmpeg is never invoked on missing/empty artifacts.

Source

Thrown at app/services/bgm.py:165

            check=False,
        )
    except subprocess.TimeoutExpired as exc:
        raise BgmServiceError("FFmpeg background music validation timed out") from exc
    except OSError as exc:
        raise BgmServiceError("failed to run FFmpeg for background music validation") from exc
    if decoded.returncode != 0:
        raise BgmUploadError("uploaded file must contain a decodable audio stream")


def validate_audio_file(file_path: str, timeout_seconds: int = 120) -> None:
    """
    校验磁盘上的音频文件可由项目 FFmpeg 完整解码。

    上传预检通常只需 30 秒;Sonilo 生成的配乐最长可达 6 分钟,因此对外提供
    可调整超时的复用入口。服务只依赖 FFmpeg,不要求系统额外安装 FFprobe。
    """
    if not os.path.isfile(file_path) or os.path.getsize(file_path) <= 0:
        raise BgmUploadError("background music file is empty or missing")
    _validate_audio(file_path, timeout_seconds=timeout_seconds)


def _stage_bgm_upload(filename: str, source: BinaryIO) -> tuple[str, str, int]:
    """
    将上传流写入同目录临时文件,并返回安全文件名、临时路径和字节数。

    WebUI 的上传预检和最终持久化必须使用完全相同的分块读取、大小限制与文件名
    规则,否则可能出现界面显示可用、点击生成后却被服务端拒绝的状态分裂。
    临时文件由调用方在完成音频探测后删除或原子替换。
    """
    safe_name = sanitize_upload_filename(filename)
    try:
        target_dir = uploaded_bgm_dir(create=True)
    except OSError as exc:
        raise BgmServiceError("failed to prepare background music storage") from exc
    temp_path = ""
    total_bytes = 0

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Confirm the file exists and has bytes before calling validation: os.path.isfile(p) and os.path.getsize(p) > 0.
  2. If a generated track is empty, the upstream generation step failed — re-run it rather than retrying validation.
  3. Use absolute paths resolved from a single tasks/storage root to avoid working-directory races.

Example fix

# before
validate_audio_file(possibly_missing_path)

# after
import os
if not os.path.isfile(possibly_missing_path) or os.path.getsize(possibly_missing_path) <= 0:
    raise RuntimeError(f"audio artifact missing or empty: {possibly_missing_path!r}")
validate_audio_file(possibly_missing_path)
Defensive patterns

Strategy: validation

Validate before calling

import os
def artifact_ready(path: str) -> bool:
    return os.path.isfile(path) and os.path.getsize(path) > 0

Prevention

When it happens

Trigger: Calling validate_audio_file on a path where the file was deleted or moved between staging and validation; a generated BGM file that was created but never written (0 bytes) due to a failed upstream step; a directory path passed instead of a file.

Common situations: Race between generation completion and validation in async pipelines; disk-full producing empty outputs; path typos or wrong working directory making os.path.isfile false.

Related errors


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