zylon-ai/private-gpt · error · ValueError

Binary block must contain base64 data before upload

Error message

Binary block must contain base64 data before upload

What it means

Raised in the binary-block-to-S3 upload transform (binary_block_decorators.py) when the block's source is not (or does not contain) a Base64BinarySource with non-empty data. The transform's job is to move inline base64 payloads into a temporary S3 bucket and replace them with a URI source; it explicitly skips URIBinarySource blocks that are already URLs, and raises for everything else — e.g. local-path sources or empty base64 payloads.

Source

Thrown at private_gpt/components/tools/binary_block_decorators.py:101

    blob_visibility: BlobVisibilityMode,
    raise_on_error: bool = False,
) -> None:
    """Transform a media block IN PLACE based on visibility mode.

    Modifies the block's source directly to preserve type and serialization.

    Args:
        block: The block to transform (must have source and optional filename attrs)
        blob_visibility: The visibility mode (PUBLIC or PRIVATE)
        raise_on_error: Whether to raise on errors or log and skip
    """
    try:
        # If source is already URI-backed, skip transformation.
        if isinstance(block.source, URIBinarySource) and _is_url(block.source.url):
            return

        if not isinstance(block.source, Base64BinarySource):
            raise ValueError("Binary block must contain base64 data before upload")
        if not block.source.data:
            raise ValueError("Binary block must contain base64 data before upload")

        # Get S3 helper from injector
        s3_helper = get_global_injector().get(S3Helper)

        # Generate unique identifiers
        mime_type = block.source.media_type or "application/octet-stream"
        if block.filename is None:
            block.filename = _generate_filename(mime_type)
        object_name = str(uuid.uuid4())
        bucket_name = settings().s3.temporary_bucket_name

        # Convert base64 data to bytes
        bytes_data = _extract_bytes_from_data(block.source.data)

        # Upload to S3
        s3_url = await asyncio.to_thread(

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Ensure the block went through base64 ingestion before the S3 upload transform.
  2. Check block.source type at runtime; skip blocks that are already URI-backed or lack data.
  3. If mixed pipelines are expected, invoke the transform with raise_on_error=False so non-base64 blocks are logged and skipped.
  4. For empty Base64BinarySource.data: fix the producer that created the block with empty content.

Example fix

# before
transform_block_for_upload(block, blob_visibility, raise_on_error=True)  # raises

# after
if isinstance(block.source, Base64BinarySource) and block.source.data:
    transform_block_for_upload(block, blob_visibility, raise_on_error=True)
else:
    logger.warning("Skipping non-base64 block during upload: %r", block.source)
Defensive patterns

Strategy: type-guard

Validate before calling

from private_gpt.components.tools.binary_block_decorators import _is_url  # or local equivalent

def block_is_uploadable(block) -> bool:
    src = getattr(block, "source", None)
    if isinstance(src, URIBinarySource) and _is_url(src.url):
        return False  # already uploaded
    return isinstance(src, Base64BinarySource) and bool(src.data)

Type guard

def has_base64_payload(block) -> bool:
    src = getattr(block, "source", None)
    return isinstance(src, Base64BinarySource) and bool(src.data)

Try / catch

try:
    transform_block_for_upload(block, visibility, raise_on_error=True)
except ValueError as e:
    if "must contain base64 data" in str(e):
        logger.warning("skipping non-base64 block: %r", block.source)
    else:
        raise

Prevention

When it happens

Trigger: Calling the upload decorator on a block whose source is a LocalPathBinarySource/other source class, or a Base64BinarySource with data='' / data=None. The raise_on_error flag controls whether this raises or is logged and skipped.

Common situations: Upload pipeline run before base64 ingestion populated the block; blocks created from local file paths that were never converted to base64; upstream ingestion silently storing empty data; calling the transform twice where a previous pass consumed the data.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/940693f489e71ef0. Report an issue: GitHub.