affaan-m/ECC · error · FalError

fal upload failed; provider details omitted

Error message

fal upload failed; provider details omitted

What it means

falapi.upload() calls fal_client.upload_file() to push the local file to fal.ai storage. If the upload raises for any reason, it raises FalError('fal upload failed; provider details omitted') with the original exception deliberately unchained (`from None`) because provider error strings may embed keys, signed URLs, or payload contents. This is a sanitized wrapper: the real cause is hidden on purpose, so diagnostics must come from context, not the exception.

Solutions

  1. Re-check FAL_KEY validity (dashboard -> keys) since auth failures are the most common hidden cause, then retry the upload.
  2. Retry with a smaller/stabler network path: check file size against provider limits, disable interfering proxies/VPN, and retry on a stable connection.
  3. Work around the upload when possible — pass publicly reachable URLs as inputs instead of local files, or retry with backoff if it is transient.
  4. If it persists, reproduce outside the pipeline with a minimal `fal_client.upload_file(...)` script to see the raw provider error (locally only, never in logs/CI), then fix the root cause.

Example fix

# before
except FalError:
    pass  # provider details omitted, no idea why

# after
try:
    size = Path(asset).stat().st_size
except OSError:
    raise
if size > MAX_UPLOAD_BYTES:
    raise ValueError(f"{asset} exceeds fal.ai upload limit ({size} bytes)")
for attempt in range(3):  # bounded retry with backoff
    try:
        url = upload(asset)
        break
    except FalError:
        time.sleep(2 ** attempt)
else:
    raise RuntimeError(f"upload of {asset} failed after 3 attempts")
Defensive patterns

Strategy: retry

Validate before calling

from pathlib import Path
p = Path(path)
assert p.is_file(), f"missing file: {p}"
size = p.stat().st_size
assert size <= MAX_UPLOAD_BYTES, f"{p.name} too large for fal upload: {size} bytes"

Try / catch

try:
    url = upload(path)
except FalError:
    # provider details are intentionally omitted; check key + network, then retry
    verify_fal_key_valid()
    url = upload(path) if attempts_left() else raise_upload_failure(path)

Prevention

When it happens

Trigger: upload() (via upload_many()) in live mode, after api_key() succeeds, when _fal().upload_file(str(p)) raises — network interruption during upload, provider 401/403 on the storage endpoint, file size above provider limits, timeout on slow connections, or transient fal.ai storage errors.

Common situations: Expired or revoked FAL_KEY (401 mid-session); large multi-megabyte model/asset files failing on flaky networks or corporate proxies; payload exceeding fal.ai's upload size limits; firewall/VPN blocking the storage host; rate limiting after many consecutive uploads.

Related errors


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

Appendix: source

Thrown at skills/taste-application/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)