{"record":{"id":"121bae59a96af02a","repo":"kataras/iris","slug":"multipart-related-next-part-read-w","errorCode":null,"errorMessage":"multipart related: next part: read: %w","messagePattern":"multipart related: next part: read: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"context/context.go","lineNumber":3089,"sourceCode":"\t\tsetBody(ctx.request, body) // so the ctx.request.Body works\n\t\tdefer restoreBody()        // so the next ctx.GetBody calls work.\n\t}\n\n\tmultipartReader := multipart.NewReader(ctx.request.Body, params[\"boundary\"])\n\tfor {\n\t\tpart, err := multipartReader.NextPart()\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\treturn MultipartRelated{}, fmt.Errorf(\"multipart related: next part: %w\", err)\n\t\t}\n\t\tdefer part.Close()\n\n\t\tb, err := io.ReadAll(part)\n\t\tif err != nil {\n\t\t\treturn MultipartRelated{}, fmt.Errorf(\"multipart related: next part: read: %w\", err)\n\t\t}\n\n\t\tcontentID := part.Header.Get(\"Content-ID\")\n\t\tcontentIDs = append(contentIDs, contentID)\n\t\tcontents[contentID] = MultipartRelatedContent{ // replace if same Content-ID appears, which it shouldn't.\n\t\t\tID:      contentID,\n\t\t\tHeaders: http.Header(part.Header),\n\t\t\tBody:    b,\n\t\t}\n\t}\n\n\tif len(contents) != len(contentIDs) {\n\t\tcontentIDs = distinctStrings(contentIDs)\n\t}\n\n\tresult := MultipartRelated{\n\t\tContentIDs: contentIDs,\n\t\tContents:   contents,","sourceCodeStart":3071,"sourceCodeEnd":3107,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/context/context.go#L3071-L3107","documentation":"Same ReadMultipartRelated flow, but this error wraps a failure from io.ReadAll(part): the part boundary was found and NextPart succeeded, yet reading the part's bytes failed (connection dropped, truncated part, or read error). It distinguishes 'failed while reading part contents' from 'failed locating the next part'.","triggerScenarios":"ctx.ReadMultipartRelated where a part's body is incomplete: client disconnect mid-part, chunked transfer interrupted, or an I/O error on the request stream.","commonSituations":"Timeouts on very large parts (images/embedded attachments in MTOM); mobile clients dropping connections; gateway buffering limits cutting off part bodies.","solutions":["Check the wrapped error for connection-reset/timeout and ask the client to retry the upload.","Raise server timeouts and body-size limits for large multipart payloads.","Return 400/408 appropriately instead of 500 when the client aborted.","Verify client-side that the full part body is flushed before closing the connection."],"exampleFix":"// before\nmr, err := ctx.ReadMultipartRelated()\nif err != nil { return err }\n// after\nmr, err := ctx.ReadMultipartRelated()\nif err != nil {\n    if errors.Is(err, io.ErrUnexpectedEOF) {\n        ctx.StatusCode(iris.StatusBadRequest)\n        return errors.New(\"truncated multipart part\")\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"if ctx.Request().ContentLength > maxSize {\n    return errors.New(\"payload too large\")\n}","typeGuard":null,"tryCatchPattern":"mr, err := ctx.ReadMultipartRelated()\nif err != nil {\n    if errors.Is(err, io.ErrUnexpectedEOF) {\n        ctx.StatusCode(iris.StatusBadRequest)\n        return errors.New(\"truncated multipart part\")\n    }\n    return err\n}","preventionTips":["Increase timeouts for uploads containing large parts","Detect client disconnects (connection reset) and answer 408/400 rather than 500","Have clients verify upload completion (checksums) on flaky networks"],"tags":["go","iris","multipart","io","network"],"backgroundTag":"multipart-part-read-failed","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}