{"record":{"id":"e25ab8e8cb2e087e","repo":"affaan-m/ECC","slug":"image-to-3d-needs-at-least-one-image-falapi","errorCode":null,"errorMessage":"image_to_3d needs at least one image","messagePattern":"image_to_3d needs at least one image","errorType":"validation","errorClass":"FalError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/taste/falapi.py","lineNumber":516,"sourceCode":"    it. When in doubt, send one image.\n\n    ``pbr`` requests physically-based maps (metallic, roughness, normal). Without\n    them the mesh lights like painted cardboard in Blender, which defeats the\n    point of minting it. It is ignored when ``geometry_only`` is set.\n\n    Note the endpoint's own input guidance: simple background, single object,\n    object filling >50% of frame. Busy reference stills - collages, wide shots,\n    anything with several subjects - produce garbage meshes. Generate a clean\n    single-object plate first if the pack's stills are not that.\n    \"\"\"\n    if views:\n        payload: dict = {k: v for k, v in views.items() if k in VIEW_FIELDS and v}\n        if \"input_image_url\" not in payload:\n            raise FalError(\"views must include 'input_image_url' (the front view)\")\n    else:\n        urls = [image_url] if isinstance(image_url, str) else list(image_url)\n        if not urls:\n            raise FalError(\"image_to_3d needs at least one image\")\n        payload = {f: u for f, u in zip(VIEW_FIELDS, urls[:len(VIEW_FIELDS)])}\n\n    payload[\"generate_type\"] = \"Geometry\" if geometry_only else \"Normal\"\n    if not geometry_only:\n        payload[\"enable_pbr\"] = bool(pbr)\n    if face_count:\n        # Endpoint range is 40k-1.5M; clamp rather than let it 422.\n        payload[\"face_count\"] = int(max(40_000, min(1_500_000, face_count)))\n\n    result = submit(ENDPOINTS[\"image_to_3d\"], payload, timeout)\n    return _mesh_url(result, ENDPOINTS[\"image_to_3d\"])\n\n\ndef text_to_3d(prompt: str, *, pbr: bool = True, timeout: int = 900) -> str:\n    \"\"\"Mint a textured GLB from a description. Returns the mesh URL.\n\n    The complement to image_to_3d: use it for props the reference *implies*\n    but never shows cleanly enough to lift - the pack's spec describes the","sourceCodeStart":498,"sourceCodeEnd":534,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/taste/falapi.py#L498-L534","documentation":"When image_to_3d is called without a views dict, it builds the image list from image_url (a single string or an iterable). If that list ends up empty, there is no image to send to the 3D generation endpoint and the library raises FalError before submitting.","triggerScenarios":"image_to_3d(None) or image_to_3d('') or image_to_3d([]) — any call where views is falsy and image_url resolves to an empty list.","commonSituations":"A variable holding the image URL was never populated because an earlier generation step failed silently; passing an empty list after filtering out None entries from a multi-image pipeline; accidentally passing views={} which is falsy and falls into the else branch.","solutions":["Pass at least one non-empty image URL via image_url","If passing an iterable, check its length is >= 1 before calling","If intending multi-view input, pass a views dict containing 'input_image_url' instead"],"exampleFix":"# before\nimage_to_3d(urls)  # urls may be []\n# after\nif not urls:\n    raise ValueError('need at least one image for image_to_3d')\nimage_to_3d(urls)","handlingStrategy":"validation","validationCode":"urls = [image_url] if isinstance(image_url, str) else list(image_url or [])\nif not urls:\n    raise ValueError('image_to_3d requires at least one image URL')","typeGuard":"def has_images(image_url) -> bool:\n    if isinstance(image_url, str): return bool(image_url)\n    return bool(image_url)","tryCatchPattern":null,"preventionTips":["Assert the image URL variable is populated before calling image_to_3d","Propagate failures from earlier generation steps instead of silently passing None/[]","Don't pass views={} expecting a fallback — it is falsy and hits this branch","Validate URLs are non-empty https strings at pipeline boundaries"],"tags":["validation","argument","empty-input","fal"],"backgroundTag":"empty-required-field","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}