{"record":{"id":"242aa435862e09f2","repo":"affaan-m/ECC","slug":"views-must-include-input-image-url-the-front-view-falapi","errorCode":null,"errorMessage":"views must include 'input_image_url' (the front view)","messagePattern":"views must include 'input_image_url' \\(the front view\\)","errorType":"validation","errorClass":"FalError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/taste/falapi.py","lineNumber":512,"sourceCode":"    ``{\"input_image_url\": front, \"back_image_url\": back}``. Passing a bare\n    list assigns images to :data:`VIEW_FIELDS` in order, which is a guess and\n    is only correct if the caller actually sorted them that way; a wrong angle\n    label is worse than omitting the view entirely, because the model trusts\n    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:","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/taste/falapi.py#L494-L530","documentation":"image_to_3d accepts an optional views dict of multi-view images, but the fal.ai Tripo-style endpoint requires the front view under the key 'input_image_url'. If views is provided but that key is absent or empty after filtering (only known VIEW_FIELDS with truthy values are kept), the library raises FalError instead of submitting an incomplete payload.","triggerScenarios":"Calling image_to_3d(image_url, views={'back_image_url': 'https://...'}) or views={'input_image_url': None} or views={'input_image_url': ''} — i.e. any views dict that, after filtering to non-empty VIEW_FIELDS keys, lacks 'input_image_url'.","commonSituations":"Developer misreads the views API and passes only back/side views; keys are correct but values are empty strings or None because upstream URL extraction failed; typo'd key name like 'input_image' that gets filtered out.","solutions":["Include 'input_image_url' with a non-empty front-view URL in the views dict","Verify each views key is one of VIEW_FIELDS and its value is a non-empty URL string","If you only have one image, omit views entirely and pass it via image_url instead"],"exampleFix":"# before\nimage_to_3d(img, views={'back_image_url': back})\n# after\nimage_to_3d(img, views={'input_image_url': front, 'back_image_url': back})","handlingStrategy":"validation","validationCode":"if views is not None:\n    cleaned = {k: v for k, v in views.items() if v}\n    assert cleaned.get('input_image_url'), \"views requires a non-empty 'input_image_url'\"","typeGuard":"def has_front_view(views: dict) -> bool:\n    return bool(views) and bool(views.get('input_image_url'))","tryCatchPattern":null,"preventionTips":["Always pass the front view as 'input_image_url' first when using views","Use only documented VIEW_FIELDS keys — filtered-out typos fail with this error","Check that view URLs are non-empty strings before calling","Omit views entirely for single-image input instead of passing partial dicts"],"tags":["validation","api","argument","fal"],"backgroundTag":"missing-required-argument","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"}