affaan-m/ECC · error · FalError

image_to_3d needs at least one image

Error message

image_to_3d needs at least one image

What it means

Argument guard in image_to_3d: the call was made with no image inputs. The image-to-3d endpoint requires at least one reference image (and works best with a clean single-object plate) to produce a mesh.

Solutions

  1. Pass at least one image URL (the front view) in image_url
  2. Check that the upstream step that produced the image list actually emitted entries
  3. If you have multiple views, pass them in VIEW_FIELDS order (front first)
  4. Validate the list is non-empty before calling image_to_3d

Example fix

// before
urls = collect_stills()  # may be empty
url = image_to_3d(image_url=urls)
// after
urls = collect_stills()
if not urls:
    raise SystemExit("no stills to convert; run the render step first")
url = image_to_3d(image_url=urls)
Defensive patterns

Strategy: validation

Validate before calling

urls = image_urls if isinstance(image_urls, (list, tuple)) else [image_urls]
if not urls or not all(isinstance(u, str) and u for u in urls):
    raise SystemExit("image_to_3d needs at least one non-empty image URL")

Try / catch

try:
    url = image_to_3d(image_url=stills)
except FalError:
    logging.error("no images passed to image_to_3d; stills=%r", stills)
    raise

Prevention

When it happens

Trigger: Calling image_to_3d(image_url=[]) , image_url=None coerced via list(), or passing an empty iterable; also passing a falsy image_url with no views dict.

Common situations: An upstream step (batch render, screenshot loop) produced zero images; filtering removed all candidate images before the call; misreading the API and passing a list of prompts instead of image URLs.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at skills/taste-application/scripts/falapi.py:516

    it. When in doubt, send one image.

    ``pbr`` requests physically-based maps (metallic, roughness, normal). Without
    them the mesh lights like painted cardboard in Blender, which defeats the
    point of minting it. It is ignored when ``geometry_only`` is set.

    Note the endpoint's own input guidance: simple background, single object,
    object filling >50% of frame. Busy reference stills - collages, wide shots,
    anything with several subjects - produce garbage meshes. Generate a clean
    single-object plate first if the pack's stills are not that.
    """
    if views:
        payload: dict = {k: v for k, v in views.items() if k in VIEW_FIELDS and v}
        if "input_image_url" not in payload:
            raise FalError("views must include 'input_image_url' (the front view)")
    else:
        urls = [image_url] if isinstance(image_url, str) else list(image_url)
        if not urls:
            raise FalError("image_to_3d needs at least one image")
        payload = {f: u for f, u in zip(VIEW_FIELDS, urls[:len(VIEW_FIELDS)])}

    payload["generate_type"] = "Geometry" if geometry_only else "Normal"
    if not geometry_only:
        payload["enable_pbr"] = bool(pbr)
    if face_count:
        # Endpoint range is 40k-1.5M; clamp rather than let it 422.
        payload["face_count"] = int(max(40_000, min(1_500_000, face_count)))

    result = submit(ENDPOINTS["image_to_3d"], payload, timeout)
    return _mesh_url(result, ENDPOINTS["image_to_3d"])


def text_to_3d(prompt: str, *, pbr: bool = True, timeout: int = 900) -> str:
    """Mint a textured GLB from a description. Returns the mesh URL.

    The complement to image_to_3d: use it for props the reference *implies*
    but never shows cleanly enough to lift - the pack's spec describes the

View on GitHub (pinned to 8321021c54)