harry0703/MoneyPrinterTurbo · error · ValueError

custom audio file must be task-local or an existing server-s

Error message

custom audio file must be task-local or an existing server-side file

What it means

Raised when resolving a custom audio file: the value was not task-local (file_security.resolve_path_within_directory already failed), so the code fell back to treating it as a server-relative path, and realpath+commonpath proved it resolves outside the project root (or commonpath itself raised, for example a path on a different drive on Windows). This is a path-containment guard: relative custom audio must stay inside the project directory.

Source

Thrown at app/services/task.py:367

            requested_file,
        )
    except ValueError as exc:
        task_dir_error = exc

    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:
    """

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Fix the client to send either a task-local filename (file uploaded into this task's directory) or a relative path that stays under the project root.
  2. Audit the sent path for traversal segments, absolute paths, and symlinks; resolve symlinks before submitting.
  3. If the intended file legitimately lives outside the project, copy it into the task directory and reference the copy.
  4. Note the nested-try quirk: any ValueError raised inside the commonpath block (including the explicit containment raise and cross-drive errors) is re-wrapped with this message, so check the __cause__ chain to tell traversal apart from other commonpath failures.

Example fix

# before
custom_audio_file = "../../shared/bgm.mp3"
# after (copy into the task and reference the task-local name)
custom_audio_file = "bgm.mp3"  # uploaded to this task's directory
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
import app.utils.utils as utils

def custom_audio_is_safe(custom_audio_file: str) -> bool:
    root = Path(utils.root_dir()).resolve()
    p = Path(custom_audio_file)
    if p.is_absolute():
        return True  # server-managed path; existence checked separately
    resolved = (root / p).resolve()
    return resolved == root or root in resolved.parents

Try / catch

try:
    audio = resolve_custom_audio_file(task_id, custom_audio_file)
except ValueError as exc:
    if "must be task-local or an existing server-side file" in str(exc):
        # containment violation: reject the request, never coerce or normalize the path
        raise HTTPException(400, str(exc)) from exc
    raise

Prevention

When it happens

Trigger: custom_audio_file containing parent-directory traversal segments (for example targeting /etc/passwd or /home/user/x.mp3); a symlink whose realpath escapes the project root; on Windows, a relative-looking path that commonpath evaluates onto another drive; a task-dir lookup that failed for an unrelated reason (task directory missing) pushing a benign relative path into the server-path branch where the guard then trips.

Common situations: Clients sending user-typed file paths verbatim; symlinked uploads pointing to system paths; malformed path strings containing backslashes or drive letters; scanner or pen-test probes attempting traversal.

Related errors


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