{"record":{"id":"830b586628ce95de","repo":"harry0703/MoneyPrinterTurbo","slug":"custom-audio-file-does-not-exist-or-is-not-a-file","errorCode":null,"errorMessage":"custom audio file does not exist or is not a file","messagePattern":"custom audio file does not exist or is not a file","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"app/services/task.py","lineNumber":372,"sourceCode":"    server_audio_file = path.realpath(\n        requested_file\n        if path.isabs(requested_file)\n        else path.join(utils.root_dir(), requested_file)\n    )\n    if not path.isabs(requested_file):\n        project_root = path.realpath(utils.root_dir())\n        try:\n            if path.commonpath([project_root, server_audio_file]) != project_root:\n                raise ValueError(\n                    \"relative custom audio paths must stay within the project directory\"\n                )\n        except ValueError as exc:\n            raise ValueError(\n                \"custom audio file must be task-local or an existing server-side file\"\n            ) from exc\n\n    if not path.isfile(server_audio_file):\n        raise ValueError(\n            \"custom audio file does not exist or is not a file\"\n        ) from task_dir_error\n\n    return server_audio_file\n\n\ndef _resolve_reusable_voice_preview(\n    task_id: str,\n    params,\n    video_script: str,\n    voice_preview: dict | None,\n) -> tuple[str, float, object] | None:\n    \"\"\"\n    校验并解析 WebUI 提交的完整试听缓存。\n\n    该载荷不是公开 API 参数，只能来自当前进程的 WebUI。即便如此，后台任务\n    仍重新核对文案和全部配音参数，并限制音频位于当前任务目录；任何不一致都\n    回退普通 TTS，不让过期试听污染正式成片。","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/services/task.py#L354-L390","documentation":"Raised at the final step of custom-audio resolution: containment checks passed (or the path was absolute) but the resolved server-side path is not an existing regular file. The 'from task_dir_error' chain records that the earlier task-local lookup also failed, so the message means: the code fell back to server paths and the file is not there.","triggerScenarios":"custom_audio_file names a file that was deleted or never uploaded; a typo or wrong extension in the filename; an absolute path pointing to a directory; the task-local file expected but the task directory lookup failed earlier, so the name was re-resolved against the project root where it does not exist; a case-sensitive filename mismatch on Linux.","commonSituations":"Upload racing with task start (file not yet written); referencing a server file by a path from a different deployment or machine (absolute paths in Docker vs host); filename case differences after moving from macOS to Linux; stale task records referencing removed files.","solutions":["Verify the file exists at the resolved path on the server (check case and extension).","If it was meant to be task-local, confirm the upload actually landed in that task's directory and re-upload if not.","For absolute paths in containers, make sure the path is valid inside the container filesystem, not the host's.","Await upload completion before creating the task that references the file."],"exampleFix":"# before: task created before upload finishes\nupload_audio(task_id, data)  # async, not awaited\ncreate_task({\"custom_audio_file\": \"bgm.mp3\"})\n# after\nawait upload_audio(task_id, data)\ncreate_task({\"custom_audio_file\": \"bgm.mp3\"})","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef custom_audio_exists(task_dir: str, custom_audio_file: str) -> bool:\n    return (Path(task_dir) / custom_audio_file).is_file()","typeGuard":null,"tryCatchPattern":"try:\n    audio = resolve_custom_audio_file(task_id, custom_audio_file)\nexcept ValueError as exc:\n    if \"does not exist or is not a file\" in str(exc):\n        raise HTTPException(404, f\"custom audio file not found: {custom_audio_file}\") from exc\n    raise","preventionTips":["Await or confirm the upload completed before creating a task that references the file.","Match filename case exactly on Linux and validate existence client-side for server paths before submission.","For absolute paths in containers, verify the path from inside the container, not the host."],"tags":["file-not-found","custom-audio","validation","upload"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}