BerriAI/litellm · error · ValueError

Nova Canvas image edit does not support tuple FileTypes. Pas

Error message

Nova Canvas image edit does not support tuple FileTypes. Pass a file-like object, bytes, or a base64-encoded string.

What it means

OpenAI's FileTypes union includes (filename, content[, content_type]) tuples. Nova Canvas edits do not handle the tuple form, so after checking file-like, bytes, str, and PathLike inputs, _file_types_to_b64 explicitly raises ValueError for tuples instead of silently mis-encoding them.

Source

Thrown at litellm/llms/bedrock/image_edit/amazon_nova_canvas_image_edit_transformation.py:148

def _file_types_to_b64(image: FileTypes | None) -> str:
    """Encode OpenAI image input to base64 string for Nova Canvas."""
    if image is None:
        raise ValueError("Nova Canvas image edit requires an image input")
    if hasattr(image, "read") and callable(getattr(image, "read", None)):
        if hasattr(image, "seek"):
            image.seek(0)
        image_bytes: Final = image.read()
        return base64.b64encode(image_bytes).decode("utf-8")
    if isinstance(image, bytes):
        return base64.b64encode(image).decode("utf-8")
    if isinstance(image, str):
        return image
    if isinstance(image, os.PathLike):
        with open(image, "rb") as f:
            return base64.b64encode(f.read()).decode("utf-8")
    if isinstance(image, tuple):
        raise ValueError(
            "Nova Canvas image edit does not support tuple FileTypes. "
            "Pass a file-like object, bytes, or a base64-encoded string."
        )
    return base64.b64encode(bytes(image)).decode("utf-8")


def _supports_nova_canvas_image_edit_from_model_cost(model: str) -> bool:
    """
    True when model_cost has supports_nova_canvas_image_edit for a resolved catalog key.

    get_model_info / ModelInfoBase omit arbitrary JSON keys, so we read model_cost
    directly (same idea as supports_* bare_entry fallback).
    """
    import litellm as _litellm

    if not model:
        return False

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Unwrap the tuple client-side: pass the file object, bytes, base64 string, or filesystem path directly.
  2. For (name, bytes) tuples use the second element; for (name, fileobj, mime) use the fileobj.
  3. If using a proxy, ensure it forwards multipart file objects, not tuple descriptors.

Example fix

# before
image = ("cat.png", png_bytes, "image/png")  # tuple -> ValueError
# after
image = png_bytes            # bytes
# or: image = open("cat.png", "rb")
# or: image = "cat.png"       # path
Defensive patterns

Strategy: type-guard

Validate before calling

def unwrap_file_types(v):
    """Return a form nova-canvas accepts: file-like, bytes, str, or path."""
    if isinstance(v, tuple):
        return v[1]  # (name, content[, mime]) -> content
    return v

Type guard

def is_tuple_file_types(v: object) -> bool:
    return isinstance(v, tuple)

Prevention

When it happens

Trigger: Passing image or mask as ('cat.png', b'...') or ('cat.png', open(...), 'image/png') to a bedrock nova-canvas image edit; some HTTP clients/SDKs build multipart files as tuples by default.

Common situations: Reusing tuple-style file payloads that other litellm file APIs accept; converting an OpenAI SDK call where files= accepts tuples; proxy middleware normalizing files to tuples.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/2f1e96c5a5d67694. Report an issue: GitHub.