{"record":{"id":"11cf0154538ae544","repo":"OpenFeign/feign","slug":"there-are-no-headers-at-all","errorCode":null,"errorMessage":"There are no headers at all.","messagePattern":"There are no headers at all\\.","errorType":"exception","errorClass":"HttpMessageNotReadableException","httpStatus":null,"severity":"error","filePath":"form-spring/src/main/java/feign/form/spring/converter/SpringManyMultipartFilesReader.java","lineNumber":89,"sourceCode":"    this.bufSize = bufSize;\n  }\n\n  @Override\n  protected boolean canWrite(MediaType mediaType) {\n    return false; // Class NOT meant for writing multipart/form-data HTTP bodies\n  }\n\n  @Override\n  protected boolean supports(Class<?> clazz) {\n    return MultipartFile[].class == clazz;\n  }\n\n  @Override\n  protected MultipartFile[] readInternal(\n      Class<? extends MultipartFile[]> clazz, HttpInputMessage inputMessage) throws IOException {\n    val headers = inputMessage.getHeaders();\n    if (headers == null) {\n      throw new HttpMessageNotReadableException(\"There are no headers at all.\", inputMessage);\n    }\n\n    MediaType contentType = headers.getContentType();\n    if (contentType == null) {\n      throw new HttpMessageNotReadableException(\"Content-Type is missing.\", inputMessage);\n    }\n\n    val boundaryBytes = getMultiPartBoundary(contentType);\n    MultipartStream multipartStream =\n        new MultipartStream(inputMessage.getBody(), boundaryBytes, bufSize, null);\n\n    val multiparts = new LinkedList<ByteArrayMultipartFile>();\n    for (boolean nextPart = multipartStream.skipPreamble();\n        nextPart;\n        nextPart = multipartStream.readBoundary()) {\n      ByteArrayMultipartFile multiPart;\n      try {\n        multiPart = readMultiPart(multipartStream);","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/form-spring/src/main/java/feign/form/spring/converter/SpringManyMultipartFilesReader.java#L71-L107","documentation":"SpringManyMultipartFilesReader.readInternal() throws HttpMessageNotReadableException when the HttpInputMessage has null headers, because the boundary needed to parse a multipart body is derived from the Content-Type header.","triggerScenarios":"Using the custom SpringManyMultipartFilesReader HttpMessageConverter to decode a response whose HttpInputMessage returns null getHeaders().","commonSituations":"Custom Client/Response implementations that build an HttpInputMessage without headers; mocking layers that omit headers; misconfigured converter usage on non-multipart messages.","solutions":["Ensure the Response/HttpInputMessage supplies non-null HttpHeaders","Set a proper multipart Content-Type header (with boundary) on the response being decoded","Fix custom Client or MockWebServer stubs to include headers"],"exampleFix":"// before\nreturn new MockClientResponse(body); // headers missing\n// after\nreturn MockClientResponse.builder()\n    .headers(HttpHeaders) // includes Content-Type: multipart/mixed; boundary=...\n    .body(body)\n    .build();","handlingStrategy":"validation","validationCode":"HttpHeaders h = message.getHeaders();\nif (h == null || h.getContentType() == null) {\n  throw new IllegalStateException(\"Multipart response requires headers with Content-Type\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  MultipartFile[] files = reader.read(type, message);\n} catch (HttpMessageNotReadableException e) {\n  // response lacked headers or Content-Type; handle malformed response\n}","preventionTips":["Ensure custom Client/Response implementations always populate HttpHeaders","Include Content-Type with boundary on multipart responses","Test decoders against stubs that mirror real server headers"],"tags":["multipart","deserialization","http-headers"],"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"}