{"record":{"id":"225cb015b5ec5665","repo":"harry0703/MoneyPrinterTurbo","slug":"background-music-file-is-empty-or-missing","errorCode":null,"errorMessage":"background music file is empty or missing","messagePattern":"background music file is empty or missing","errorType":"validation","errorClass":"BgmUploadError","httpStatus":400,"severity":"error","filePath":"app/services/bgm.py","lineNumber":165,"sourceCode":"            check=False,\n        )\n    except subprocess.TimeoutExpired as exc:\n        raise BgmServiceError(\"FFmpeg background music validation timed out\") from exc\n    except OSError as exc:\n        raise BgmServiceError(\"failed to run FFmpeg for background music validation\") from exc\n    if decoded.returncode != 0:\n        raise BgmUploadError(\"uploaded file must contain a decodable audio stream\")\n\n\ndef validate_audio_file(file_path: str, timeout_seconds: int = 120) -> None:\n    \"\"\"\n    校验磁盘上的音频文件可由项目 FFmpeg 完整解码。\n\n    上传预检通常只需 30 秒；Sonilo 生成的配乐最长可达 6 分钟，因此对外提供\n    可调整超时的复用入口。服务只依赖 FFmpeg，不要求系统额外安装 FFprobe。\n    \"\"\"\n    if not os.path.isfile(file_path) or os.path.getsize(file_path) <= 0:\n        raise BgmUploadError(\"background music file is empty or missing\")\n    _validate_audio(file_path, timeout_seconds=timeout_seconds)\n\n\ndef _stage_bgm_upload(filename: str, source: BinaryIO) -> tuple[str, str, int]:\n    \"\"\"\n    将上传流写入同目录临时文件，并返回安全文件名、临时路径和字节数。\n\n    WebUI 的上传预检和最终持久化必须使用完全相同的分块读取、大小限制与文件名\n    规则，否则可能出现界面显示可用、点击生成后却被服务端拒绝的状态分裂。\n    临时文件由调用方在完成音频探测后删除或原子替换。\n    \"\"\"\n    safe_name = sanitize_upload_filename(filename)\n    try:\n        target_dir = uploaded_bgm_dir(create=True)\n    except OSError as exc:\n        raise BgmServiceError(\"failed to prepare background music storage\") from exc\n    temp_path = \"\"\n    total_bytes = 0","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/services/bgm.py#L147-L183","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm the file exists and has bytes before calling validation: os.path.isfile(p) and os.path.getsize(p) > 0.","If a generated track is empty, the upstream generation step failed — re-run it rather than retrying validation.","Use absolute paths resolved from a single tasks/storage root to avoid working-directory races."],"exampleFix":"# before\nvalidate_audio_file(possibly_missing_path)\n\n# after\nimport os\nif not os.path.isfile(possibly_missing_path) or os.path.getsize(possibly_missing_path) <= 0:\n    raise RuntimeError(f\"audio artifact missing or empty: {possibly_missing_path!r}\")\nvalidate_audio_file(possibly_missing_path)","handlingStrategy":"validation","validationCode":"import os\ndef artifact_ready(path: str) -> bool:\n    return os.path.isfile(path) and os.path.getsize(path) > 0","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate existence and non-zero size immediately before FFmpeg work.","Propagate generation failures instead of letting empty files reach validation.","Resolve artifact paths from a single absolute storage root."],"tags":["file-existence","audio","bgm","validation"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}