siyuan-note/siyuan · error · Base64ImageSizeLimitError

batch

Error message

batch

What it means

addBase64ImageBatchSize accumulates the byte size of base64 images queued for a single upload batch. When the running total (currentBytes + fileBytes) exceeds BASE64_IMAGE_BATCH_MAX_BYTES, it throws a Base64ImageSizeLimitError with kind "batch", meaning the whole batch would exceed the configured size limit. This protects the editor from oversized upload payloads that would fail or time out.

Solutions

  1. Split the image into a new batch: flush/start a new upload batch before adding this file, keeping each batch under BASE64_IMAGE_BATCH_MAX_BYTES
  2. Catch Base64ImageSizeLimitError and surface a user-facing message telling them the batch exceeds the size limit and to upload fewer/smaller images at once
  3. Check the incoming fileBytes against BASE64_IMAGE_BATCH_MAX_BYTES before enqueueing and reject images that alone exceed the limit
  4. Compress or downscale the image before base64 encoding to reduce its byte size

Example fix

// before
let batchBytes = 0;
images.forEach(img => { batchBytes = addBase64ImageBatchSize(batchBytes, img.bytes); });
// after
let batchBytes = 0;
for (const img of images) {
  if (batchBytes + img.bytes > BASE64_IMAGE_BATCH_MAX_BYTES) {
    await flushBatch(); // start a new batch
    batchBytes = 0;
  }
  batchBytes = addBase64ImageBatchSize(batchBytes, img.bytes);
}
Defensive patterns

Strategy: validation

Validate before calling

function canAddToBatch(currentBytes, fileBytes) {
  return currentBytes + fileBytes <= BASE64_IMAGE_BATCH_MAX_BYTES;
}

Type guard

const isBase64ImageSizeLimitError = (e: unknown): e is Base64ImageSizeLimitError =>
  e instanceof Base64ImageSizeLimitError && e.kind === "batch";

Try / catch

try {
  totalBytes = addBase64ImageBatchSize(currentBytes, fileBytes);
} catch (e) {
  if (e instanceof Base64ImageSizeLimitError) {
    startNewBatch(); // flush and continue with a fresh batch
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling addBase64ImageBatchSize with (currentBytes, fileBytes) whose sum exceeds BASE64_IMAGE_BATCH_MAX_BYTES, e.g. repeatedly adding large base64-encoded images (pasted screenshots) until the cumulative batch bytes pass the cap.

Common situations: Users paste many or very large screenshots into the editor; a plugin adds multiple base64 images to one upload queue; the batch limit is lowered via configuration while old queued images remain.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/a6a9b4bf704eb059. Report an issue: GitHub.

Appendix: source

Thrown at app/src/protyle/upload/base64File.ts:33

        super(`Base64 image ${scope} size ${actualBytes} exceeds ${maxBytes} bytes`);
        this.name = "Base64ImageSizeLimitError";
    }
}

export const isBase64ImageSizeLimitError = (error: unknown): error is Base64ImageSizeLimitError =>
    error instanceof Base64ImageSizeLimitError;

export const assertBase64ImageItemSize = (actualBytes: number, maxBytes?: number) => {
    const itemMaxBytes = Math.min(maxBytes ?? BASE64_IMAGE_ITEM_MAX_BYTES, BASE64_IMAGE_ITEM_MAX_BYTES);
    if (actualBytes > itemMaxBytes) {
        throw new Base64ImageSizeLimitError("item", actualBytes, itemMaxBytes);
    }
};

export const addBase64ImageBatchSize = (currentBytes: number, fileBytes: number) => {
    const totalBytes = currentBytes + fileBytes;
    if (totalBytes > BASE64_IMAGE_BATCH_MAX_BYTES) {
        throw new Base64ImageSizeLimitError("batch", totalBytes, BASE64_IMAGE_BATCH_MAX_BYTES);
    }
    return totalBytes;
};

const startsWith = (bytes: Uint8Array, signature: number[]) =>
    signature.every((value, index) => bytes[index] === value);

const detectBase64ImageFormat = (bytes: Uint8Array): IBase64ImageFormat | undefined => {
    if (startsWith(bytes, [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])) {
        return {extension: "png", mime: "image/png"};
    }
    if (startsWith(bytes, [0xFF, 0xD8, 0xFF])) {
        return {extension: "jpg", mime: "image/jpeg"};
    }
    if (startsWith(bytes, [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]) ||
        startsWith(bytes, [0x47, 0x49, 0x46, 0x38, 0x39, 0x61])) {
        return {extension: "gif", mime: "image/gif"};
    }

View on GitHub (pinned to 9f775e8a12)