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
- 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.
- Audit the sent path for traversal segments, absolute paths, and symlinks; resolve symlinks before submitting.
- If the intended file legitimately lives outside the project, copy it into the task directory and reference the copy.
- 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
- Only accept task-local filenames from end users; server-side paths should come from a curated picker, not free text.
- Never normalize or strip parent-directory segments to fix this error; it is a security guard, so fix the source of the path instead.
- On Windows deployments, remember cross-drive relative paths also land here via commonpath's ValueError.
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
- empty path is not allowed
- custom audio file does not exist or is not a file
- path is outside the allowed directory
- file does not exist
- {request_id}: invalid filename
AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14).
Data as JSON: /api/errors/3c757ae12ea7eb86.
Report an issue: GitHub.