kataras/iris · error
multipart related: next part: %w
Error message
multipart related: next part: %w
What it means
Returned by ReadMultipartRelated when multipartReader.NextPart() fails with an error other than io.EOF while iterating the parts of a multipart/related body. It wraps the underlying parsing error and means the multipart stream was malformed or the connection failed between parts.
Source
Thrown at context/context.go:3083
// * remember, Request.Body has no Bytes(), we have to consume them first
// and after re-set them to the body, this is the only solution.
body, restoreBody, err := GetBody(ctx.request, true)
if err != nil {
return MultipartRelated{}, fmt.Errorf("multipart related: body copy because of iris.Configuration.DisableBodyConsumptionOnUnmarshal: %w", err)
}
setBody(ctx.request, body) // so the ctx.request.Body works
defer restoreBody() // so the next ctx.GetBody calls work.
}
multipartReader := multipart.NewReader(ctx.request.Body, params["boundary"])
for {
part, err := multipartReader.NextPart()
if err != nil {
if err == io.EOF {
break
}
return MultipartRelated{}, fmt.Errorf("multipart related: next part: %w", err)
}
defer part.Close()
b, err := io.ReadAll(part)
if err != nil {
return MultipartRelated{}, fmt.Errorf("multipart related: next part: read: %w", err)
}
contentID := part.Header.Get("Content-ID")
contentIDs = append(contentIDs, contentID)
contents[contentID] = MultipartRelatedContent{ // replace if same Content-ID appears, which it shouldn't.
ID: contentID,
Headers: http.Header(part.Header),
Body: b,
}
}
if len(contents) != len(contentIDs) {View on GitHub (pinned to 7bedaf55a0)
Solutions
- Inspect the wrapped error (%w) to distinguish parse errors from network failures.
- Validate the client's Content-Type boundary matches the actual delimiter used.
- Return 400 to the client for malformed multipart payloads.
- Capture the raw body (when recording is enabled) to debug the exact bytes that failed.
Example fix
// before
mr, err := ctx.ReadMultipartRelated()
if err != nil { return err }
// after
mr, err := ctx.ReadMultipartRelated()
if err != nil {
ctx.StatusCode(iris.StatusBadRequest)
return fmt.Errorf("invalid multipart/related payload: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
ct := ctx.GetContentType()
if !strings.HasPrefix(ct, "multipart/related") {
return errors.New("expected multipart/related content type")
} Type guard
func isMultipartRelated(ctx *context.Context) bool {
return strings.HasPrefix(ctx.GetContentType(), "multipart/related")
} Try / catch
mr, err := ctx.ReadMultipartRelated()
if err != nil {
if strings.Contains(err.Error(), "next part:") && !strings.Contains(err.Error(), "read:") {
ctx.StatusCode(iris.StatusBadRequest)
return fmt.Errorf("malformed multipart/related: %w", err)
}
return err
} Prevention
- Verify the client's boundary parameter matches the actual payload delimiters
- Return 400 for parse errors instead of 500
- Capture raw bodies when recording is enabled to debug malformed payloads
When it happens
Trigger: ctx.ReadMultipartRelated where NextPart returns a non-EOF error: malformed boundary, truncated body, missing final boundary, or an underlying read error on the connection.
Common situations: Clients generating malformed multipart/related payloads (SOAP MTOM, XOP packages); interrupted uploads; mismatched boundary parameter in Content-Type; proxies re-encoding the body.
Related errors
- multipart related: body copy because of iris.Configuration.D
- multipart related: next part: read: %w
- context: read body: cannot bind multipart/related: use ReadM
- ErrEmptyFormField
- dest directory: %s: eval symlinks: %w
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/faa1bd0b01ab4409.
Report an issue: GitHub.