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

  1. Inspect the wrapped error (%w) to distinguish parse errors from network failures.
  2. Validate the client's Content-Type boundary matches the actual delimiter used.
  3. Return 400 to the client for malformed multipart payloads.
  4. 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

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


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/faa1bd0b01ab4409. Report an issue: GitHub.