PaddlePaddle/PaddleOCR · error · ValueError

Invalid Base64 input: {e}. Ensure the string is complete and

Error message

Invalid Base64 input: {e}. Ensure the string is complete and correctly padded.

What it means

ValueError from decode_base64_payload in paddleocr_mcp/utils.py when base64.b64decode(payload, validate=True) raises. validate=True rejects any non-alphabet character, so whitespace, URL-safe characters (-_,), missing padding, or embedded newlines all fail; the message chains the underlying binascii error and reminds about padding.

Source

Thrown at mcp_server/paddleocr_mcp/utils.py:50

def is_base64(value: str) -> bool:
    pattern = r"^[A-Za-z0-9+/]+={0,2}$"
    return bool(re.fullmatch(pattern, value))


def extract_base64_payload(input_data: str) -> str:
    if input_data.startswith("data:"):
        if "," not in input_data:
            raise ValueError("Invalid data URL: expected a comma after the MIME type.")
        return input_data.split(",", 1)[1]
    return input_data


def decode_base64_payload(payload: str) -> bytes:
    try:
        return base64.b64decode(payload, validate=True)
    except Exception as e:
        raise ValueError(
            f"Invalid Base64 input: {e}. "
            "Ensure the string is complete and correctly padded."
        ) from e


def infer_file_type_from_bytes(data: bytes) -> Optional[str]:
    import puremagic

    mime = puremagic.from_string(data, mime=True)
    if mime.startswith("image/"):
        return "image"
    if mime == "application/pdf":
        return "pdf"
    return None

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Strip whitespace/newlines: `payload = "".join(payload.split())`.
  2. Fix padding: `payload += "=" * (-len(payload) % 4)`.
  3. Convert URL-safe to standard: `payload.replace("-", "+").replace("_", "/")` before sending.
  4. Re-encode the source bytes to guarantee a clean string.

Example fix

// before
payload = "iVBORw0KGgoAAAANSUhEUg...\nAAA="  # contains newline
decode_base64_payload(payload)  # ValueError

// after
payload = "".join(payload.split())
payload += "=" * (-len(payload) % 4)
decode_base64_payload(payload)
Defensive patterns

Strategy: validation

Validate before calling

import base64

def base64_decodable(payload: str) -> bool:
    cleaned = "".join(payload.split())
    cleaned += "=" * (-len(cleaned) % 4)
    try:
        base64.b64decode(cleaned, validate=True)
        return True
    except Exception:
        return False

Type guard

import re

def is_standard_base64(value: str) -> bool:
    """True for non-empty standard-alphabet base64 with valid padding."""
    return bool(re.fullmatch(r"[A-Za-z0-9+/]+={0,2}", value)) and len(value) % 4 == 0

Try / catch

try:
    data = decode_base64_payload(payload)
except ValueError as e:
    if "Base64" in str(e):
        cleaned = "".join(payload.split())
        cleaned += "=" * (-len(cleaned) % 4)
        data = decode_base64_payload(cleaned)  # single deterministic repair
    else:
        raise

Prevention

When it happens

Trigger: Base64 copied with line wraps/newlines; URL-safe base64 (using - and _) passed without conversion; truncated payload missing 1-2 padding '=' chars; payload still percent-encoded or wrapped in a data URL fragment.

Common situations: Clients embedding base64 in JSON where whitespace survived; output of base64.urlsafe_b64encode fed directly; LLM tool calls truncating long strings.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/9dd16c2472cda9e1. Report an issue: GitHub.