Skip to content

Multipart Parts Out of Order (400)

https://docs.ankatech.co/errors/multipart-part-order

A streaming endpoint received its parts in the wrong order: the payload arrived before the small part that describes it.

{
  "type": "https://docs.ankatech.co/errors/multipart-part-order",
  "title": "Multipart Parts Out Of Order",
  "status": 400,
  "detail": "The 'metadata' part must be sent before the 'file' part. A streaming endpoint reads the request in order and cannot look ahead.",
  "instance": "/api/v3/migration/stream/analyze-pkcs7",
  "correlationId": "550e8400-e29b-41d4-a716-446655440000"
}

Why the order is part of the contract

Every streaming endpoint reads the request once, forward, without buffering it. That is what lets a multi-gigabyte payload be processed with flat memory — and it is also why the order cannot be relaxed: by the time the payload has streamed past, there is nothing left to rewind to in order to go back and read the small part.

So the small part is not merely conventional first. It is first because the server cannot act on the payload without it.


Which part must come first

The small part's name depends on the operation, and getting the name wrong produces a different error — a missing required part, not an ordering one.

Endpoint Small part Payload part
POST /api/v3/crypto/stream/decrypt header file
POST /api/v3/crypto/stream/decrypt-verify header file
POST /api/v3/crypto/stream/encrypt metadata file
POST /api/v3/crypto/stream/reencrypt header file
POST /api/v3/crypto/stream/resign metadata file
POST /api/v3/crypto/stream/sign metadata file
POST /api/v3/crypto/stream/sign-encrypt metadata file
POST /api/v3/crypto/stream/verify metadata file
POST /api/v3/interoperability/encrypt metadata file
POST /api/v3/interoperability/verify metadata file
POST /api/v3/migration/stream/analyze-pkcs7 metadata file

The three operations that take header rather than metadata are the ones that open an existing JOSE object -- decrypt, decrypt-then-verify, and re-encrypt. What their small part carries is that object's own header, not metadata describing the request. Everything else, including re-sign, takes metadata.

Eleven endpoints enforce this ordering — eight taking metadata, three taking header — and the list above is exactly those. It is NOT the list of endpoints that accept multipart/form-data: POST /api/v3/migration/stream/convert-pkcs7-to-jose does, but it binds its parts through the buffering resolver rather than the streaming one, so wire order is irrelevant there and it cannot produce this error. A table derived from the specification alone would wrongly include it, because the specification records which operations take a multipart body, not which ones read it in a single forward pass.


How to resolve

Send the small part first. With curl, the order of -F arguments is the order on the wire:

curl -sS -X POST "$ANKA_BASE_URL/api/v3/migration/stream/analyze-pkcs7" \
  -H "Authorization: Bearer $TOKEN" \
  -F 'metadata={"validateCertificates":true};type=application/json' \
  -F "[email protected]"

The reverse order fails:

# ✗ 400 multipart-part-order
curl -sS -X POST "$ANKA_BASE_URL/api/v3/migration/stream/analyze-pkcs7" \
  -H "Authorization: Bearer $TOKEN" \
  -F "[email protected]" \
  -F 'metadata={"validateCertificates":true};type=application/json'

If you are building the request from a library rather than curl, check that it does not reorder parts — some HTTP clients sort multipart entries by name, which would place file before metadata.