{"record":{"id":"f1a0b6fad2ff7f7c","repo":"siyuan-note/siyuan","slug":"image-attachment-request-limit-exceeded-at-most","errorCode":null,"errorMessage":"image attachment request limit exceeded: at most %d images and %d bytes","messagePattern":"image attachment request limit exceeded: at most (.+?) images and (.+?) bytes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/attachments.go","lineNumber":61,"sourceCode":"\texpiresAt time.Time\n}\n\nvar imageInputUnsupportedCache sync.Map\n\nfunc mergeAgentAttachments(current []AgentAttachment, attachments []mcptools.ModelAttachment) (merged, added []AgentAttachment, err error) {\n\timageCount := len(current)\n\ttotalBytes := 0\n\tfor _, attachment := range current {\n\t\ttotalBytes += len(attachment.Data)\n\t}\n\n\tadded = make([]AgentAttachment, 0, len(attachments))\n\tfor _, attachment := range attachments {\n\t\tif attachment.Type != \"image\" || len(attachment.Data) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif imageCount >= maxAgentImagesPerRequest || totalBytes+len(attachment.Data) > maxAgentImageBytesPerRequest {\n\t\t\treturn current, nil, fmt.Errorf(\n\t\t\t\t\"image attachment request limit exceeded: at most %d images and %d bytes\",\n\t\t\t\tmaxAgentImagesPerRequest, maxAgentImageBytesPerRequest,\n\t\t\t)\n\t\t}\n\t\tadded = append(added, AgentAttachment{\n\t\t\tType:       attachment.Type,\n\t\t\tData:       attachment.Data,\n\t\t\tMIMEType:   attachment.MIMEType,\n\t\t\tPath:       attachment.Path,\n\t\t\tDocumentID: attachment.DocumentID,\n\t\t\tDetail:     attachment.Detail,\n\t\t\tWidth:      attachment.Width,\n\t\t\tHeight:     attachment.Height,\n\t\t})\n\t\timageCount++\n\t\ttotalBytes += len(attachment.Data)\n\t}\n\tmerged = append(append([]AgentAttachment(nil), current...), added...)","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/agent/attachments.go#L43-L79","documentation":"mergeAgentAttachments() returns an fmt.Errorf with this template when adding another image would exceed the hard caps: maxAgentImagesPerRequest (4) or maxAgentImageBytesPerRequest (20 MiB). Both imageCount (number of existing image attachments) and totalBytes are accumulated across current+added attachments before the guard.","triggerScenarios":"An agent turn attaches a 5th image, or the cumulative size of all image attachments on the request exceeds 20 MiB; calling the agent endpoint with several high-resolution screenshots pasted in one turn; attachments merged from multiple tool results in a single turn.","commonSituations":"User drags 5+ photos into the chat; an image-heavy block reference adds screenshots that push the byte total over 20 MiB; tool returns base64 images that cumulatively exceed the cap; very large PNGs from a screen-capture tool.","solutions":["Reduce the number of images to at most 4 per agent request (downscale or omit extras before sending).","Compress/resize each image so total bytes stay under 20 MiB.","Split the request into multiple turns if more than 4 images are genuinely needed.","If higher limits are operationally required, override the constants in a fork (maxAgentImagesPerRequest / maxAgentImageBytesPerRequest in kernel/agent/attachments.go) and document the trade-off."],"exampleFix":"// before\nreq := appendImages(req, allImages) // 6 images, 30 MiB\n// after\nconst maxN = 4\nif len(allImages) > maxN { allImages = allImages[:maxN] }\nfor _, img := range allImages { img = resizeTo(img, 1920, jpegQuality(85)) }\nreq := appendImages(req, allImages)","handlingStrategy":"validation","validationCode":"const maxImages = 4;\nconst maxBytes = 20 * 1024 * 1024;\nif (imageAttachments.length > maxImages) imageAttachments = imageAttachments.slice(0, maxImages);\nlet bytes = imageAttachments.reduce((n, a) => n + a.Data.length, 0);\nwhile (bytes > maxBytes && imageAttachments.length) { bytes -= imageAttachments.pop().Data.length; }","typeGuard":null,"tryCatchPattern":"merged, added, err := mergeAgentAttachments(current, incoming)\nif err != nil {\n    if strings.Contains(err.Error(), 'image attachment request limit exceeded') { /* drop or resize and retry */ }\n    return err\n}","preventionTips":["Limit client-side uploads to 4 images per agent turn.","Resize/compress images so cumulative bytes stay under 20 MiB before attaching.","Split large multi-image requests across turns.","Watch the caps in kernel/agent/attachments.go if you fork; document any change."],"tags":["agent","attachments","limits","go"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}