{"record":{"id":"986972999b0f2a28","repo":"chenhg5/cc-connect","slug":"attachment-exceeds-d-bytes","errorCode":null,"errorMessage":"attachment exceeds %d bytes","messagePattern":"attachment exceeds (.+?) bytes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/max/max.go","lineNumber":1205,"sourceCode":"\tdefer cancel()\n\treq, err := http.NewRequestWithContext(dlCtx, http.MethodGet, url, nil)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\tresp, err := p.client.Do(req)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, \"\", fmt.Errorf(\"HTTP %d\", resp.StatusCode)\n\t}\n\tdata, err := io.ReadAll(io.LimitReader(resp.Body, maxAttachmentBytes+1))\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\tif len(data) > maxAttachmentBytes {\n\t\treturn nil, \"\", fmt.Errorf(\"attachment exceeds %d bytes\", maxAttachmentBytes)\n\t}\n\treturn data, resp.Header.Get(\"Content-Type\"), nil\n}\n\n// resolveMediaURL asks MAX for the playable/downloadable URL of a video or\n// audio attachment. MAX delivers only an opaque token in the message payload\n// and exposes /videos/{token} and /audios/{token} for resolution.\nfunc (p *Platform) resolveMediaURL(ctx context.Context, kind, token string) (string, string, error) {\n\tif token == \"\" {\n\t\treturn \"\", \"\", fmt.Errorf(\"empty token\")\n\t}\n\tendpoint := \"/videos/\"\n\tif kind == \"audio\" {\n\t\tendpoint = \"/audios/\"\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, p.apiBase+endpoint+token, nil)\n\tif err != nil {\n\t\treturn \"\", \"\", err","sourceCodeStart":1187,"sourceCodeEnd":1223,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/max/max.go#L1187-L1223","documentation":"The attachment body downloaded from MAX exceeded maxAttachmentBytes. The reader is capped at maxAttachmentBytes+1 so any payload strictly larger than the limit is detected and rejected before it can exhaust memory.","triggerScenarios":"A user sends an image or file through MAX whose size is larger than maxAttachmentBytes; downloadAttachment reads maxAttachmentBytes+1 bytes and the extra byte triggers this error.","commonSituations":"Users sharing large videos/high-res photos through the bot bridge; deployment with a conservatively small maxAttachmentBytes configured.","solutions":["Increase maxAttachmentBytes if your deployment can afford larger transfers","Reply to the user that the attachment is too large to relay instead of surfacing a raw error","Check Content-Length before reading to fail fast","Compress or link to the original URL instead of downloading the full payload"],"exampleFix":"// before\ndata, ct, err := p.downloadAttachment(ctx, url)\nif err != nil { return err }\n// after\ndata, ct, err := p.downloadAttachment(ctx, url)\nif err != nil {\n\tif strings.Contains(err.Error(), \"attachment exceeds\") {\n\t\treturn sendTooLargeNotice(chatID)\n\t}\n\treturn err\n}","handlingStrategy":"validation","validationCode":"if att.Size > maxAttachmentBytes { return sendTooLargeNotice(chatID) }","typeGuard":null,"tryCatchPattern":"if _, _, err := dl(); err != nil && strings.Contains(err.Error(), \"attachment exceeds\") {\n\treturn gracefulTooLargeReply()\n}","preventionTips":["Check Content-Length before downloading when present","Set maxAttachmentBytes to a value matching your users' typical media sizes","Reply with a user-friendly size-limit message instead of a raw error"],"tags":["attachments","limit","payload-size"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}