BerriAI/litellm · error · ValueError
Max recursion depth {max_depth} reached while reading image
Error message
Max recursion depth {max_depth} reached while reading image bytes for Vertex AI Imagen image edit. What it means
Imagen edit's _read_all_bytes recursively unwraps structured image input — lists/tuples take the first non-None item, dicts are probed for 'data'/'bytes'/'content' (base64-decoded) then 'path'. A depth guard caps this recursion at DEFAULT_MAX_RECURSE_DEPTH (100 by default, overridable via the DEFAULT_MAX_RECURSE_DEPTH env var) to avoid pathological structures. Only inputs nested deeper than that cap raise this ValueError.
Source
Thrown at litellm/llms/vertex_ai/image_edit/vertex_imagen_transformation.py:290
mask_bytes: Final = self._read_all_bytes(mask_image)
mask_base64: Final = base64.b64encode(mask_bytes).decode("utf-8")
mask_reference: Final = {
"referenceType": "REFERENCE_TYPE_MASK",
"referenceId": len(reference_images) + 1,
"referenceImage": {"bytesBase64Encoded": mask_base64},
"maskImageConfig": {
"maskMode": "MASK_MODE_USER_PROVIDED",
"dilation": 0.03, # Default dilation value (not configurable via OpenAI API)
},
}
reference_images.append(mask_reference)
return reference_images
def _read_all_bytes(self, image: Any, depth: int = 0, max_depth: int = DEFAULT_MAX_RECURSE_DEPTH) -> bytes:
if depth > max_depth:
raise ValueError(
f"Max recursion depth {max_depth} reached while reading image bytes for Vertex AI Imagen image edit."
)
if isinstance(image, (list, tuple)):
for item in image:
if item is not None:
return self._read_all_bytes(item, depth=depth + 1, max_depth=max_depth)
raise ValueError("Unsupported image type for Vertex AI Imagen image edit.")
if isinstance(image, dict):
for key in ("data", "bytes", "content"):
if key in image and image[key] is not None:
value = image[key]
if isinstance(value, str):
try:
return base64.b64decode(value)
except Exception:
continueView on GitHub (pinned to 77b7c6c40c)
Solutions
- Flatten the input before the call — reduce it to bytes, BytesIO, or a shallow {'data': '<base64>'} dict
- Find and fix the wrapping loop that adds a layer per iteration (the real bug is upstream)
- As a last resort for legitimately deep structures, raise the cap via env var DEFAULT_MAX_RECURSE_DEPTH=200
Example fix
# before: loop adds a layer per retry
for attempt in range(retries):
payload = [payload] # grows nesting each pass
resp = litellm.image_edit(model='vertex_ai/imagen-...', prompt=p, image=payload)
# after: send a flat payload
payload = unwrap_to_bytes(payload) # collapse to bytes once
resp = litellm.image_edit(model='vertex_ai/imagen-...', prompt=p, image=payload) Defensive patterns
Strategy: validation
Validate before calling
def nesting_depth(v, d=0):
if isinstance(v, (list, tuple)) and v:
return nesting_depth(v[0], d + 1)
return d
assert nesting_depth(image) < 100, 'image payload suspiciously nested; flatten to bytes' Try / catch
try:
resp = litellm.image_edit(model='vertex_ai/imagen-...', prompt=p, image=image)
except ValueError as e:
if 'Max recursion depth' in str(e):
raise ValueError('image payload nesting bug — flatten to bytes before calling') from e
raise Prevention
- Normalize image payloads to bytes at the system boundary; never forward arbitrary user JSON
- Audit loops that wrap payloads (payload = [payload]) per retry or per pipeline stage
- Add a depth assertion in preprocessing so bad structures fail with your own error message
When it happens
Trigger: image=[[[[ ... ]]]] with more than 100 nesting levels; a dict chain like {'data': {'bytes': {'content': ...}}} deeper than 100; usually generated by buggy glue code that re-wraps images in a loop (e.g. image = [image] applied repeatedly).
Common situations: Loop bugs that wrap payloads one more layer per iteration; data pipelines that forward arbitrary user JSON as the image field; test fixtures generated recursively.
Related errors
- Vertex AI Imagen image edit requires at least one reference
- Vertex AI Imagen image edit requires a prompt.
- Unsupported image type for Vertex AI Imagen image edit.
- Unsupported image input: plain string values are not accepte
- Unsupported image input: filesystem paths are not accepted f
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/db7e7d449799692b.
Report an issue: GitHub.