affaan-m/ECC · error · FalError

fal upload failed; provider details omitted

Error message

fal upload failed; provider details omitted

What it means

FalError raised by upload() when _fal().upload_file() throws. Provider details are deliberately omitted (`from None`) because fal exceptions can embed signed URLs and keys. The upload cache is not populated on failure, so a later retry re-attempts the POST.

Solutions

  1. Retry the upload — failure details are hidden, so first check general connectivity and fal.ai status
  2. Validate FAL_KEY is still valid (an auth rejection surfaces as this generic error)
  3. Try a smaller/compressed file if the asset is very large
  4. Re-run with dry-run disabled but network logging enabled outside the library to capture the underlying cause

Example fix

// before
url = falapi.upload(path)  # FalError: fal upload failed; provider details omitted
// after
import time
for attempt in range(3):
    try:
        url = falapi.upload(path)
        break
    except falapi.FalError:
        time.sleep(2 ** attempt)
else:
    raise RuntimeError(f"upload failed after retries: {path}")
Defensive patterns

Strategy: retry

Validate before calling

from pathlib import Path
p = Path(path)
if not p.is_file() or p.stat().st_size == 0:
    raise FileNotFoundError(f"bad upload source: {p}")

Try / catch

import time
for attempt in range(3):
    try:
        url = falapi.upload(path)
        break
    except falapi.FalError:
        if attempt == 2:
            raise
        time.sleep(2 ** attempt)

Prevention

When it happens

Trigger: upload() in live mode: api_key() succeeds, then `_fal().upload_file(str(p))` raises — network failure, provider 4xx/5xx, oversized file, or expired credentials.

Common situations: Unstable network during multi-megabyte image upload; fal.ai incident/outage; uploading a very large asset that the provider rejects; invalid FAL_KEY.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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

Appendix: source

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

    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))

    with _UPLOAD_LOCK:
        _UPLOAD_CACHE[key] = url
    return url


def upload_many(paths: Iterable[str | Path]) -> list[str]:
    return [upload(p) for p in paths]


def clear_upload_cache() -> None:
    with _UPLOAD_LOCK:
        _UPLOAD_CACHE.clear()


# ---------------------------------------------------------------------------
# response parsing

View on GitHub (pinned to 8321021c54)