{"record":{"id":"eac9eda2757ea82b","repo":"BerriAI/litellm","slug":"amazon-nova-canvas-inpainting-requires-either-mask","errorCode":null,"errorMessage":"Amazon Nova Canvas INPAINTING requires either maskPrompt or maskImage (use OpenAI mask= for maskImage, or pass maskPrompt in optional params). See https://docs.aws.amazon.com/nova/latest/userguide/image-gen-req-resp-structure.html","messagePattern":"Amazon Nova Canvas INPAINTING requires either maskPrompt or maskImage \\(use OpenAI mask= for maskImage, or pass maskPrompt in optional params\\)\\. See https://docs\\.aws\\.amazon\\.com/nova/latest/userguide/image-gen-req-resp-structure\\.html","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/bedrock/image_edit/amazon_nova_canvas_image_edit_transformation.py","lineNumber":111,"sourceCode":"        }\n    # Explicit taskType must be INPAINTING or omitted from here on; anything else is invalid.\n    if task_type is not None and str(task_type).strip() != \"\":\n        if task_type != \"INPAINTING\":\n            raise ValueError(\n                f\"Unsupported Amazon Nova Canvas taskType: {task_type!r}. \"\n                \"Use BACKGROUND_REMOVAL, OUTPAINTING, IMAGE_VARIATION, INPAINTING, \"\n                \"or omit taskType for automatic routing (mask → INPAINTING, else IMAGE_VARIATION).\"\n            )\n    if mask_b64 is not None or mask_prompt is not None or task_type == \"INPAINTING\":\n        in_params: Final[dict[str, Any]] = {\"image\": image_b64, \"text\": text}\n        if mask_prompt is not None:\n            in_params[\"maskPrompt\"] = mask_prompt\n        elif mask_b64 is not None:\n            in_params[\"maskImage\"] = mask_b64\n        if negative_text is not None:\n            in_params[\"negativeText\"] = negative_text\n        if \"maskPrompt\" not in in_params and \"maskImage\" not in in_params:\n            raise ValueError(\n                \"Amazon Nova Canvas INPAINTING requires either maskPrompt or maskImage \"\n                \"(use OpenAI mask= for maskImage, or pass maskPrompt in optional params). \"\n                \"See https://docs.aws.amazon.com/nova/latest/userguide/image-gen-req-resp-structure.html\"\n            )\n        return {\"taskType\": \"INPAINTING\", \"inPaintingParams\": in_params}\n    var_params: Final[dict[str, Any]] = {\n        \"images\": [image_b64],\n        \"text\": text,\n    }\n    if negative_text is not None:\n        var_params[\"negativeText\"] = negative_text\n    if similarity_strength is not None:\n        var_params[\"similarityStrength\"] = similarity_strength\n    return {\n        \"taskType\": \"IMAGE_VARIATION\",\n        \"imageVariationParams\": var_params,\n    }\n","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/bedrock/image_edit/amazon_nova_canvas_image_edit_transformation.py#L93-L129","documentation":"AWS requires Nova Canvas inPaintingParams to include either maskImage or maskPrompt. LiteLLM enters the INPAINTING branch when a mask/maskPrompt is present or taskType='INPAINTING' is explicit; if the branch is entered but neither mask field ended up in in_params (i.e. explicit INPAINTING with no mask supplied), it raises this ValueError before sending the request.","triggerScenarios":"litellm.image_edit(model='bedrock/amazon.nova-canvas-v1:0', image=source, prompt='add a hat', taskType='INPAINTING') with neither mask=<file> nor maskPrompt in optional params.","commonSituations":"Assuming INPAINTING works from the prompt alone; passing the mask under a key the transformer does not read; migrating from Stability edits where mask wiring differs.","solutions":["Pass a mask image: litellm.image_edit(..., mask=open('mask.png', 'rb')) (OpenAI-style mask= becomes maskImage)","Or pass maskPrompt in optional params describing the region to inpaint","If no mask is intended, drop taskType so the call routes to IMAGE_VARIATION"],"exampleFix":"# before\nresp = litellm.image_edit(\n    model=\"bedrock/amazon.nova-canvas-v1:0\",\n    image=open(\"cat.png\", \"rb\"),\n    prompt=\"a red collar\",\n    taskType=\"INPAINTING\",\n)\n\n# after\nresp = litellm.image_edit(\n    model=\"bedrock/amazon.nova-canvas-v1:0\",\n    image=open(\"cat.png\", \"rb\"),\n    prompt=\"a red collar\",\n    taskType=\"INPAINTING\",\n    mask=open(\"collar-mask.png\", \"rb\"),   # or maskPrompt=\"the neck area\"\n)","handlingStrategy":"validation","validationCode":"def validate_inpainting_call(kwargs: dict) -> None:\n    if kwargs.get(\"taskType\") == \"INPAINTING\":\n        assert kwargs.get(\"mask\") is not None or kwargs.get(\"maskPrompt\"), (\n            \"INPAINTING needs mask= (maskImage) or maskPrompt\"\n        )\n\nvalidate_inpainting_call(kwargs)","typeGuard":"def has_inpainting_mask(kwargs: dict) -> bool:\n    \"\"\"True when INPAINTING kwargs carry maskImage or maskPrompt.\"\"\"\n    if kwargs.get(\"taskType\") != \"INPAINTING\":\n        return True\n    return kwargs.get(\"mask\") is not None or bool(kwargs.get(\"maskPrompt\"))","tryCatchPattern":"try:\n    resp = litellm.image_edit(...)\nexcept ValueError as e:\n    if \"INPAINTING requires either maskPrompt or maskImage\" in str(e):\n        raise UserInputError(\"Pass mask=<file> or maskPrompt for inpainting\") from e\n    raise","preventionTips":["Treat mask/maskPrompt as required fields in your edit-request dataclass when taskType is INPAINTING","Prefer letting LiteLLM auto-route (omit taskType) when the mask is optional in your product flow","Log the full kwargs (minus image bytes) on validation failures to catch key-name drift"],"tags":["bedrock","nova-canvas","image-edit","inpainting","mask","client-side-validation"],"backgroundTag":"missing-required-argument","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}