unslothai/unsloth · error · ValueError
Invalid base64 image data: {exc}
Error message
Invalid base64 image data: {exc} What it means
Raised while parsing a client-supplied image (img2img/inpaint/outpaint/upscale base) when base64.b64decode raises binascii.Error or ValueError: the payload after stripping a data: URL prefix is not valid base64. It surfaces to the client as a 400.
Source
Thrown at studio/backend/core/inference/diffusion.py:375
"""Decode a base64 (optionally ``data:`` URL) image string to a PIL image.
The image-conditioned workflows (img2img / inpaint / edit) transport the input
image and mask as base64 in the JSON request, so this is the single decode path.
A mask is decoded as single-channel ``L``; the source image as ``RGB``."""
import base64
import binascii
import io
from PIL import Image
raw = data.strip()
if raw.startswith("data:"):
# data:[<mime>][;base64],<payload>
_, _, raw = raw.partition(",")
try:
blob = base64.b64decode(raw, validate = False)
except (binascii.Error, ValueError) as exc:
raise ValueError(f"Invalid base64 image data: {exc}") from exc
# Bound the decoded size: 4096px covers txt2img 2048, upscales and outpaint canvases.
max_side = 4096
try:
img = Image.open(io.BytesIO(blob))
# Reject from the header before img.load() so a huge-dimension file cannot spike memory.
w, h = img.size
if w > max_side or h > max_side:
raise ValueError(f"Image is too large ({w}x{h}); maximum is {max_side}px per side.")
img.load()
except ValueError:
raise # the size guard's own message; don't wrap it as a decode error
except Exception as exc: # noqa: BLE001 — surfaced as a 400 to the client
raise ValueError(f"Could not decode image: {exc}") from exc
return img.convert(mode)
def _snap_to_multiple(img: Any, multiple: int = 16) -> Any:
"""Resize a PIL image so both sides are multiples of ``multiple`` (rounded to nearest,View on GitHub (pinned to 203007d190)
Solutions
- Regenerate the payload: strip whitespace/newlines, and re-encode the source image with base64.b64encode
- Send as a proper data URL 'data:image/png;base64,<payload>' — the parser handles the prefix
- Verify the client is not truncating large request bodies (check proxy/server max body size)
Example fix
# before
open("img.png", "rb").read() # raw bytes sent as text
# after
base64.b64encode(open("img.png", "rb").read()).decode() Defensive patterns
Strategy: validation
Validate before calling
import base64, binascii
def valid_b64_image_payload(data: str) -> bool:
raw = data.strip()
if raw.startswith("data:"):
raw = raw.partition(",")[2]
try:
base64.b64decode(raw, validate=False)
return True
except (binascii.Error, ValueError):
return False Try / catch
try:
img = parse_b64_image(data)
except ValueError as e:
if "Invalid base64" in str(e):
return JSONResponse(status_code=400, content={"detail": str(e)}) Prevention
- Strip whitespace/newlines from base64 before sending
- Encode with a standard library (PIL save → base64.b64encode), never hand-copied blobs
- Check server/proxy max request body size for large images
When it happens
Trigger: Truncated or whitespace-mangled base64 string; payload containing characters outside the base64 alphabet; a data: URL whose header portion was included because it lacked the ',' separator handled by partition; JSON-escaped newlines corrupting the string.
Common situations: Frontend truncating large images in JSON; copy-paste of base64 with line breaks; double-encoding (base64 of base64); sending a raw file URL where bytes are expected.
Related errors
- Image is too large ({w}x{h}); maximum is {max_side}px per si
- Could not decode image: {exc}
- each reference image must be at most 32 MiB (base64)
- Unknown model_kind '{model_kind}'. Expected one of {sorted(_
- Local base_repo is not a diffusers pipeline directory (no {i
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/c3a88899ec7b3496.
Report an issue: GitHub.