{"record":{"id":"9127b310e942d821","repo":"siyuan-note/siyuan","slug":"item","errorCode":null,"errorMessage":"item","messagePattern":"item","errorType":"validation","errorClass":"Base64ImageSizeLimitError","httpStatus":null,"severity":"warning","filePath":"app/src/protyle/upload/base64File.ts","lineNumber":26,"sourceCode":"\nexport type TBase64ImageSizeLimitScope = \"item\" | \"batch\";\n\nexport class Base64ImageSizeLimitError extends Error {\n    readonly code = \"BASE64_IMAGE_SIZE_LIMIT\";\n\n    constructor(readonly scope: TBase64ImageSizeLimitScope, readonly actualBytes: number, readonly maxBytes: number) {\n        super(`Base64 image ${scope} size ${actualBytes} exceeds ${maxBytes} bytes`);\n        this.name = \"Base64ImageSizeLimitError\";\n    }\n}\n\nexport const isBase64ImageSizeLimitError = (error: unknown): error is Base64ImageSizeLimitError =>\n    error instanceof Base64ImageSizeLimitError;\n\nexport const assertBase64ImageItemSize = (actualBytes: number, maxBytes?: number) => {\n    const itemMaxBytes = Math.min(maxBytes ?? BASE64_IMAGE_ITEM_MAX_BYTES, BASE64_IMAGE_ITEM_MAX_BYTES);\n    if (actualBytes > itemMaxBytes) {\n        throw new Base64ImageSizeLimitError(\"item\", actualBytes, itemMaxBytes);\n    }\n};\n\nexport const addBase64ImageBatchSize = (currentBytes: number, fileBytes: number) => {\n    const totalBytes = currentBytes + fileBytes;\n    if (totalBytes > BASE64_IMAGE_BATCH_MAX_BYTES) {\n        throw new Base64ImageSizeLimitError(\"batch\", totalBytes, BASE64_IMAGE_BATCH_MAX_BYTES);\n    }\n    return totalBytes;\n};\n\nconst startsWith = (bytes: Uint8Array, signature: number[]) =>\n    signature.every((value, index) => bytes[index] === value);\n\nconst detectBase64ImageFormat = (bytes: Uint8Array): IBase64ImageFormat | undefined => {\n    if (startsWith(bytes, [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])) {\n        return {extension: \"png\", mime: \"image/png\"};\n    }","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/app/src/protyle/upload/base64File.ts#L8-L44","documentation":"assertBase64ImageItemSize enforces the per-item byte limit (BASE64_IMAGE_ITEM_MAX_BYTES, optionally lowered by maxBytes) for images inserted as base64 data URLs; exceeding it throws Base64ImageSizeLimitError with scope 'item', carrying actual and maximum bytes.","triggerScenarios":"Pasting/dropping an image whose base64 payload exceeds the configured per-item limit — e.g. a screenshot or photo of several MB pasted directly into the editor.","commonSituations":"Pasting large screenshots from clipboard; dropping high-resolution photos; environments/config where the limit was lowered via maxBytes; offline users who can't rely on file-based upload paths.","solutions":["Use a smaller image (compress/resize before pasting)","Insert the image as a file/asset upload instead of inline base64","Raise the applicable limit if the product allows (within BASE64_IMAGE_ITEM_MAX_BYTES)","Catch isBase64ImageSizeLimitError and show the size limit message to the user"],"exampleFix":"// before\ncreateBase64ImageFile(hugeDataUrl);\n// after\ntry { assertBase64ImageItemSize(bytes, maxBytes); createBase64ImageFile(hugeDataUrl); }\ncatch (e) { if (isBase64ImageSizeLimitError(e)) showMessage(`max ${e.maxBytes} bytes`); }","handlingStrategy":"validation","validationCode":"if (dataUrl.length * 0.75 > BASE64_IMAGE_ITEM_MAX_BYTES) { showMessage(\"image too large\"); return; }","typeGuard":"const withinLimit = (bytes: number, max?: number) => bytes <= Math.min(max ?? BASE64_IMAGE_ITEM_MAX_BYTES, BASE64_IMAGE_ITEM_MAX_BYTES);","tryCatchPattern":"try { createBase64ImageFile(dataUrl); } catch (e) { if (isBase64ImageSizeLimitError(e)) showMessage(`Image exceeds ${e.maxBytes} byte limit`); }","preventionTips":["Compress/resize images before inline base64 insertion","Prefer asset-file uploads for large images","Check isBase64ImageSizeLimitError to show precise size feedback"],"tags":["upload","image","size-limit","validation"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}