affaan-m/ECC · error · FalError

cannot upload, file does not exist

Error message

cannot upload, file does not exist: {p}

What it means

FalError raised by upload() when the local file path passed for upload does not exist on disk. Checked before any provider call, and before consulting the upload cache, so no network activity happens. The message includes the offending path.

Solutions

  1. Verify the file exists before uploading: Path(path).exists() or os.path.isfile(path)
  2. Print/inspect the absolute path (Path(path).resolve()) to spot CWD or relative-path mistakes
  3. Fix the upstream step that was supposed to create the file
  4. If you already have a hosted URL, skip upload and pass the URL directly

Example fix

// before
url = falapi.upload("frames/front.png")  # FalError: cannot upload, file does not exist
// after
from pathlib import Path
p = Path("frames/front.png")
if not p.exists():
    raise FileNotFoundError(f"expected frame missing: {p.resolve()}")
url = falapi.upload(str(p))
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
p = Path(path)
if not p.is_file():
    raise FileNotFoundError(f"upload source missing: {p.resolve()}")

Try / catch

try:
    url = falapi.upload(path)
except falapi.FalError as e:
    if "does not exist" in str(e):
        print(f"Check path/CWD: {Path(path).resolve()}")

Prevention

When it happens

Trigger: Calling upload(path) (or upload_many) in live mode with a path whose Path(path).exists() is False — e.g. a frame extraction step failed earlier, a relative path resolved from the wrong working directory, or a typo'd filename.

Common situations: Pipeline stage that produces the image ran but wrote elsewhere; passing an output URL instead of a local file; deleted temp files between steps; running from a different CWD than expected.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/39b9f26df119f70c. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-distillation/scripts/taste/falapi.py:300


def _cache_key(path: Path) -> tuple[str, int, int]:
    st = path.stat()
    return (str(path.resolve()), st.st_mtime_ns, st.st_size)


def upload(path: str | Path) -> str:
    """Upload a local file and return its URL, memoized per (path, mtime, size).

    apply.py reuses the same handful of stills across every shot in a run and
    across concurrent workers; without this cache each of those becomes a
    redundant multi-megabyte POST.
    """
    if not is_dry_run():
        require_live()
    p = Path(path)
    if not p.exists():
        raise FalError(f"cannot upload, file does not exist: {p}")

    key = _cache_key(p)
    with _UPLOAD_LOCK:
        hit = _UPLOAD_CACHE.get(key)
    if hit and (is_dry_run() == hit.startswith(DRY_RUN_HOST + "/")):
        log.debug("upload cache hit: %s", p.name)
        return hit

    if is_dry_run():
        url = f"{DRY_RUN_HOST}/uploads/{_digest(str(key))}/{p.name}"
        log.info("[dry-run] would upload %s (%d bytes) -> %s", p, key[2], url)
    else:
        api_key()
        try:
            url = _fal().upload_file(str(p))
        except Exception:
            raise FalError("fal upload failed; provider details omitted") from None
        log.info("uploaded %s -> %s", p.name, safe_url(url))

View on GitHub (pinned to 8321021c54)