BerriAI/litellm · error · ValueError
Unsupported image input: plain string values that are not UR
Error message
Unsupported image input: plain string values that are not URLs are not accepted. Provide image bytes or a file-like object.
What it means
When the image argument is a plain string, _read_image_bytes only accepts strings starting with http:// or https:// (it fetches them with a 60s GET). Any other string — including local file paths, base64 data, or arbitrary text — raises ValueError telling you to supply bytes or a file-like object. Despite the message mentioning 'file path' in the sibling branch's error, this path branch does not read the filesystem.
Source
Thrown at litellm/llms/black_forest_labs/image_edit/transformation.py:212
max_depth: int = DEFAULT_MAX_RECURSE_DEPTH,
) -> bytes:
"""Read image bytes from various input types."""
if depth > max_depth:
raise ValueError(
f"Max recursion depth {max_depth} reached while reading image bytes for Black Forest Labs image edit."
)
if isinstance(image, bytes):
return image
elif isinstance(image, list):
# If it's a list, take the first image
return self._read_image_bytes(image[0], depth=depth + 1, max_depth=max_depth)
elif isinstance(image, str):
if image.startswith(("http://", "https://")):
response: Final = safe_get(litellm.module_level_client, image, timeout=60.0)
response.raise_for_status()
return response.content
else:
raise ValueError(
"Unsupported image input: plain string values that are not URLs are not accepted. "
"Provide image bytes or a file-like object."
)
elif hasattr(image, "read"):
# File-like object
pos: Final = getattr(image, "tell", lambda: 0)()
if hasattr(image, "seek"):
image.seek(0)
data: Final = image.read()
if hasattr(image, "seek"):
image.seek(pos)
return data
else:
raise ValueError(
f"Unsupported image type: {type(image)}. Expected bytes, str (URL or file path), or file-like object."
)
def transform_image_edit_request(View on GitHub (pinned to 6c2dcb801b)
Solutions
- Read local files into bytes first: image=open(path,'rb').read() or pass the open file object (it is seek-rewound automatically).
- For base64 strings, decode first: image=base64.b64decode(s).
- Host the image and pass its https URL.
- If you want path support, wrap it yourself: image=Path(p).read_bytes().
Example fix
# before
litellm.image_edit(model=..., image="/tmp/photo.png", prompt="...")
# after
with open("/tmp/photo.png", "rb") as f:
litellm.image_edit(model=..., image=f, prompt="...") Defensive patterns
Strategy: type-guard
Validate before calling
def to_image_arg(image):
if isinstance(image, str):
if image.startswith(("http://", "https://")):
return image
return open(image, "rb").read() # treat as local path
return image
image = to_image_arg(image) Type guard
def is_usable_bfl_image_str(s: str) -> bool:
return s.startswith(("http://", "https://")) Try / catch
null
Prevention
- Normalize inputs at your boundary: strings must be URLs; everything else becomes bytes or a file object.
- Decode base64 strings with base64.b64decode before passing.
- Lint for string literals passed as image that lack the http(s) scheme.
When it happens
Trigger: Passing image="/tmp/photo.png", image="data:image/png;base64,...", or any non-URL string to image_edit on a black_forest_labs model.
Common situations: Assuming local paths are supported because the other error message mentions them; passing base64-encoded bytes as a string instead of raw bytes; generating images to disk then feeding the path back for editing.
Related errors
- Max recursion depth {max_depth} reached while reading image
- Unsupported image type: {type(image)}. Expected bytes, str (
- Unknown BFL image edit model: {model_name}. Supported models
- BFL error: {response_data['errors']}
- Parameter {k} is not supported for model {model}. Supported
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/8cb679dbfbbce6d7.
Report an issue: GitHub.