siyuan-note/siyuan · error · Base64ImageSizeLimitError
BASE64_IMAGE_SIZE_LIMIT
BASE64_IMAGE_SIZE_LIMIT
Error message
Base64 image item size ${actualBytes} exceeds ${itemMaxBytes} bytes What it means
assertBase64ImageItemSize enforces a per-image byte limit when handling base64 images. The effective maximum is the caller-supplied maxBytes capped at BASE64_IMAGE_ITEM_MAX_BYTES. When the decoded image's byte size (actualBytes) exceeds that cap, a Base64ImageSizeLimitError (scope 'item', code BASE64_IMAGE_SIZE_LIMIT) is thrown with the message 'Base64 image item size ${actualBytes} exceeds ${itemMaxBytes} bytes'. It is called from createBase64ImageFile before constructing the File.
Source
Thrown at app/src/protyle/upload/base64File.ts:26
export type TBase64ImageSizeLimitScope = "item" | "batch";
export class Base64ImageSizeLimitError extends Error {
readonly code = "BASE64_IMAGE_SIZE_LIMIT";
constructor(readonly scope: TBase64ImageSizeLimitScope, readonly actualBytes: number, readonly maxBytes: number) {
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"};
}View on GitHub (pinned to 8641553a1f)
Solutions
- Decode the base64 first and check its size with a helper (base64 length * 3/4 minus padding) before calling, then downscale/recompress the image if over the limit
- Compress the image (e.g. canvas.toBlob at lower quality or rescale dimensions) and retry with the smaller payload
- Raise the caller-provided maxBytes only up to BASE64_IMAGE_ITEM_MAX_BYTES if the limit was set too strictly for your workflow
- Catch Base64ImageSizeLimitError (or use isBase64ImageSizeLimitError) and surface a user-facing message asking for a smaller image
Example fix
// before: oversized base64 hits the limit
await createBase64ImageFile(dataUrl);
// after: pre-check and compress if needed
const bytes = estimateBase64Bytes(dataUrl);
if (bytes > BASE64_IMAGE_ITEM_MAX_BYTES) {
dataUrl = await compressImage(dataUrl, BASE64_IMAGE_ITEM_MAX_BYTES);
}
await createBase64ImageFile(dataUrl); Defensive patterns
Strategy: validation
Validate before calling
// estimate decoded byte size of a base64 data URL before calling
const estimateBase64Bytes = (dataUrl: string) => {
const base64 = dataUrl.split(",")[1] || "";
const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
return Math.max(0, Math.floor(base64.length * 3 / 4) - padding);
};
if (estimateBase64Bytes(dataUrl) > BASE64_IMAGE_ITEM_MAX_BYTES) {
// compress or reject before createBase64ImageFile
} Type guard
import { isBase64ImageSizeLimitError } from "./base64File";
if (isBase64ImageSizeLimitError(err) && err.scope === "item") { /* handle per-item limit */ } Try / catch
try {
await createBase64ImageFile(dataUrl);
} catch (err) {
if (isBase64ImageSizeLimitError(err)) {
showToast(`Image too large: ${err.actualBytes} bytes (max ${err.maxBytes})`);
} else { throw err; }
} Prevention
- Always estimate decoded size from base64 length before submitting
- Downscale clipboard/pasted screenshots to a max dimension before encoding
- Compress with canvas.toBlob (JPEG/WebP) for photos; PNG screenshots grow quickly
- Never assume a caller-supplied maxBytes can exceed BASE64_IMAGE_ITEM_MAX_BYTES — it is capped
When it happens
Trigger: Call createBase64ImageFile (or directly assertBase64ImageItemSize) with a base64 data URL whose decoded payload is larger than BASE64_IMAGE_ITEM_MAX_BYTES (or the caller's smaller maxBytes override).
Common situations: Pasting or dropping a very large screenshot/clipboard image that gets base64-encoded; a plugin or script uploading oversized images via the base64 path; tightened maxBytes overrides making previously acceptable images too large.
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
- invalid custom emoji image
- image exceeds size limit: %d bytes
- image exceeds pixel limit: %d
- Agent capability name and description are required
- Account authentication failed, please login again
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/f27ca79b9cb61985.
Report an issue: GitHub.