harry0703/MoneyPrinterTurbo · error · ValueError

custom audio file does not exist or is not a file

Error message

custom audio file does not exist or is not a file

What it means

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.

Source

Thrown at app/services/task.py:372

    server_audio_file = path.realpath(
        requested_file
        if path.isabs(requested_file)
        else path.join(utils.root_dir(), requested_file)
    )
    if not path.isabs(requested_file):
        project_root = path.realpath(utils.root_dir())
        try:
            if path.commonpath([project_root, server_audio_file]) != project_root:
                raise ValueError(
                    "relative custom audio paths must stay within the project directory"
                )
        except ValueError as exc:
            raise ValueError(
                "custom audio file must be task-local or an existing server-side file"
            ) from exc

    if not path.isfile(server_audio_file):
        raise ValueError(
            "custom audio file does not exist or is not a file"
        ) from task_dir_error

    return server_audio_file


def _resolve_reusable_voice_preview(
    task_id: str,
    params,
    video_script: str,
    voice_preview: dict | None,
) -> tuple[str, float, object] | None:
    """
    校验并解析 WebUI 提交的完整试听缓存。

    该载荷不是公开 API 参数,只能来自当前进程的 WebUI。即便如此,后台任务
    仍重新核对文案和全部配音参数,并限制音频位于当前任务目录;任何不一致都
    回退普通 TTS,不让过期试听污染正式成片。

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Verify the file exists at the resolved path on the server (check case and extension).
  2. If it was meant to be task-local, confirm the upload actually landed in that task's directory and re-upload if not.
  3. For absolute paths in containers, make sure the path is valid inside the container filesystem, not the host's.
  4. Await upload completion before creating the task that references the file.

Example fix

# before: task created before upload finishes
upload_audio(task_id, data)  # async, not awaited
create_task({"custom_audio_file": "bgm.mp3"})
# after
await upload_audio(task_id, data)
create_task({"custom_audio_file": "bgm.mp3"})
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def custom_audio_exists(task_dir: str, custom_audio_file: str) -> bool:
    return (Path(task_dir) / custom_audio_file).is_file()

Try / catch

try:
    audio = resolve_custom_audio_file(task_id, custom_audio_file)
except ValueError as exc:
    if "does not exist or is not a file" in str(exc):
        raise HTTPException(404, f"custom audio file not found: {custom_audio_file}") from exc
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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