AUTOMATIC1111/stable-diffusion-webui · error · HTTPException

Invalid encoded image

Error message

Invalid encoded image

What it means

HTTP 500 raised by decode_base64_to_image when the payload was not a URL or data: URI and base64.b64decode + PIL images.read failed on it. This is the path for plain base64-encoded image strings; any exception in decoding (binascii.Error for bad base64 alphabet/padding, PIL UnidentifiedImageError for non-image bytes) is wrapped into this detail.

Source

Thrown at modules/api/api.py:99

        if opts.api_forbid_local_requests and not verify_url(encoding):
            raise HTTPException(status_code=500, detail="Request to local resource not allowed")

        headers = {'user-agent': opts.api_useragent} if opts.api_useragent else {}
        response = requests.get(encoding, timeout=30, headers=headers)
        try:
            image = images.read(BytesIO(response.content))
            return image
        except Exception as e:
            raise HTTPException(status_code=500, detail="Invalid image url") from e

    if encoding.startswith("data:image/"):
        encoding = encoding.split(";")[1].split(",")[1]
    try:
        image = images.read(BytesIO(base64.b64decode(encoding)))
        return image
    except Exception as e:
        raise HTTPException(status_code=500, detail="Invalid encoded image") from e


def encode_pil_to_base64(image):
    with io.BytesIO() as output_bytes:
        if isinstance(image, str):
            return image
        if opts.samples_format.lower() == 'png':
            use_metadata = False
            metadata = PngImagePlugin.PngInfo()
            for key, value in image.info.items():
                if isinstance(key, str) and isinstance(value, str):
                    metadata.add_text(key, value)
                    use_metadata = True
            image.save(output_bytes, format="PNG", pnginfo=(metadata if use_metadata else None), quality=opts.jpeg_quality)

        elif opts.samples_format.lower() in ("jpg", "jpeg", "webp"):
            if image.mode in ("RGBA", "P"):
                image = image.convert("RGB")

View on GitHub (pinned to 82a973c043)

Solutions

  1. Validate the string client-side: re.decode + base64.b64decode with validate=True, then PIL.Image.open before sending
  2. If sending a data URI, use the canonical 'data:image/png;base64,....' form so the split branch strips it
  3. Ensure single base64 encoding and strip whitespace/newlines: b64 = b64.replace('\n','').strip()
  4. Update/verify Pillow supports the encoded format (avif/webp extras)

Example fix

# before
b64 = open('img.png','rb').read().hex()  # wrong: hex, not base64

# after
import base64
b64 = base64.b64encode(open('img.png','rb').read()).decode()
requests.post(url+'/sdapi/v1/img2img', json={'init_images':[b64]})
Defensive patterns

Strategy: validation

Validate before calling

import base64
from PIL import Image
from io import BytesIO
def valid_image_b64(path: str) -> str:
    img = Image.open(path); img.load()  # rejects non-images early
    return base64.b64encode(open(path,'rb').read()).decode()
# additionally: base64.b64decode(s, validate=True) round-trip check

Type guard

def is_valid_b64_image(s: str) -> bool:
    try:
        img = Image.open(BytesIO(base64.b64decode(s, validate=True))); img.load()
        return True
    except Exception:
        return False

Try / catch

if resp.status_code == 500 and 'Invalid encoded image' in resp.json()['detail']:
    raise ValueError('payload was not valid base64 image bytes') from None  # fix upstream data, don't retry

Prevention

When it happens

Trigger: img2img init_images or interrogate image containing malformed base64 (missing padding, data-URI prefix not stripped because the prefix wasn't exactly 'data:image/', whitespace/newlines from JSON copying, or raw binary bytes base64'd twice); valid base64 of a non-image file (e.g. a PDF).

Common situations: Frontends that paste base64 with newlines; double-encoding (base64 of base64); sending a data URI with unusual prefix like 'data:application/octet-stream' which skips the split branch and then fails decode; files exported with different formats (webp/avif) the local Pillow build can't read.

Related errors


AI-assisted analysis of AUTOMATIC1111/stable-diffusion-webui@82a973c043 (2026-08-14). Data as JSON: /api/errors/09cdb0560bbff274. Report an issue: GitHub.