{"record":{"id":"5bf982879b08779e","repo":"OpenFeign/feign","slug":"content-type-missing-boundary-information","errorCode":null,"errorMessage":"Content-Type missing boundary information.","messagePattern":"Content-Type missing boundary information\\.","errorType":"exception","errorClass":"HttpMessageConversionException","httpStatus":null,"severity":"error","filePath":"form-spring/src/main/java/feign/form/spring/converter/SpringManyMultipartFilesReader.java","lineNumber":127,"sourceCode":"        throw new HttpMessageNotReadableException(\n            \"Multipart body could not be read.\", e, inputMessage);\n      }\n      multiparts.add(multiPart);\n    }\n    return multiparts.toArray(new ByteArrayMultipartFile[0]);\n  }\n\n  @Override\n  protected void writeInternal(\n      MultipartFile[] byteArrayMultipartFiles, HttpOutputMessage outputMessage) {\n    throw new UnsupportedOperationException(\n        getClass().getSimpleName() + \" does not support writing to HTTP body.\");\n  }\n\n  private byte[] getMultiPartBoundary(MediaType contentType) {\n    val boundaryString = unquote(contentType.getParameter(\"boundary\"));\n    if (StringUtils.hasLength(boundaryString) == false) {\n      throw new HttpMessageConversionException(\"Content-Type missing boundary information.\");\n    }\n    return boundaryString.getBytes(UTF_8);\n  }\n\n  private ByteArrayMultipartFile readMultiPart(MultipartStream multipartStream) throws IOException {\n    val multiPartHeaders =\n        splitIntoKeyValuePairs(\n            multipartStream.readHeaders(), NEWLINES_PATTERN, COLON_PATTERN, false);\n\n    val contentDisposition =\n        splitIntoKeyValuePairs(\n            multiPartHeaders.get(CONTENT_DISPOSITION),\n            SEMICOLON_PATTERN,\n            EQUALITY_SIGN_PATTERN,\n            true);\n\n    if (!contentDisposition.containsKey(\"form-data\")) {\n      throw new HttpMessageConversionException(\"Content-Disposition is not of type form-data.\");","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/form-spring/src/main/java/feign/form/spring/converter/SpringManyMultipartFilesReader.java#L109-L145","documentation":"The reader derives the multipart boundary from the boundary parameter of the Content-Type header. If the parameter is absent or empty it cannot delimit parts, so it throws HttpMessageConversionException.","triggerScenarios":"readInternal/boundaryBytes is invoked on a request whose Content-Type is multipart/* but lacks the boundary parameter (or it is empty after unquoting).","commonSituations":"A client or intermediate proxy rewrites the Content-Type and strips the boundary; hand-built multipart requests forget the boundary parameter; code sets Content-Type manually instead of letting the encoder do it.","solutions":["Ensure the client sends Content-Type like multipart/form-data; boundary=<token> and does not override the encoder-generated header","Let feign-form's encoder set the Content-Type instead of setting it manually in the interface/interceptors","Check interceptors, filters, or gateways that replace the Content-Type header"],"exampleFix":"// before\n@Headers(\"Content-Type: multipart/form-data\")\n@Post(\"/upload\") Response upload(MultipartFile file);\n// after\n@Headers(\"Content-Type: multipart/form-data\")\n// and use SpringFormEncoder, which appends the boundary automatically\nFeign.builder().encoder(new SpringFormEncoder())...","handlingStrategy":"validation","validationCode":"String ct = headers.getFirst(\"Content-Type\");\nboolean ok = ct != null && ct.matches(\"multipart/[\\w-]+;.*boundary=.+\");\nif (!ok) throw new IllegalArgumentException(\"Content-Type missing boundary parameter\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Let the multipart encoder set Content-Type; do not hardcode it in @Headers or interceptors","Audit filters/proxies that rewrite Content-Type headers","Write an integration test asserting the outgoing Content-Type contains a boundary"],"tags":["spring","multipart","content-type","boundary"],"backgroundTag":"missing-required-argument","analyzedSha":"e2a1e27560a1e68840c34f031afca88b36096e30","analyzedAt":"2026-09-10T12:37:37.238Z","contentChangedAt":"2026-09-10T12:37:37.238Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}