35

I am using Spring Boot 1.5.13 version.

I got the exception message like below.

Could not parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.4296537502689403143.5000/work/Tomcat/localhost/ROOT] is not valid

I founded out this issue in Spring Github Issues. https://github.com/spring-projects/spring-boot/issues/9616

But I still have questions of that.

  1. I am not using File Upload things in my app. But the log says that "Could not parse multipart servlet request" why is that? (I got the exception when my app uses RestTemplate (Post method)
  2. To solve the exception, I rebooted my app but It did not work right away. Although i rebooted my app, it had referenced the tomcat directory which was not exist. After a day after rebooting, it worked. I guess the directory was cached in somewhere in Spring or else..?

Please Help me out!

Sooyoung Park
  • 395
  • 1
  • 4
  • 8

10 Answers10

42
  1. The http POST methods will use these temp locations to store the post data.
  2. Some OSs like centOS will delete the temp dir frequently. So, even you set that location's permission, after some time that dir will be removed by the OS. And after you reboot, the temp dir will be different.

You can set the multipart location in application.yml:

spring:
  http:
    multipart:
      location: /data/upload_tmp

Update

As per comment by Vivek Sethi above property didn't work for me but the below one.

spring.servlet.multipart.location=/data/upload_tmp
Shark Lasers
  • 441
  • 6
  • 15
Mavlarn
  • 3,807
  • 2
  • 37
  • 57
  • 12
    This property is deprecated. Use `spring.servlet.multipart.location` instead – Vivek Sethi Oct 30 '18 at 05:42
  • 3
    For someone looking to specify a non "tmp" location, I used this: `spring.servlet.multipart.location: ${user.dir}` in my application.yml – Vivek Sethi Oct 30 '18 at 10:24
  • 3
    `spring.servlet.multipart.location` do not work on spring boot 1.5.9, but `spring.http.multipart.location` does. – Daniel Dai Dec 13 '18 at 07:25
  • @mavlarn, this is temporary solution, how to we resolve permanently, even this shows error new location not found. – Deva Jul 29 '19 at 14:38
  • I don't think it is a temporary solution. We need to make sure our application can run on different system. CentOS will delete temp directory sometime. So we need to define a temp dir location we use. So that it is not affected by System's behavior on temp dir. – Mavlarn Aug 01 '19 at 04:01
  • I am using spring boot 1.5.9 and I have configured `spring.http.multipart.location=/upload`, `new File("/upload").canWrite()` still return false while I am able to do multipart file upload, how is this possible ? – Dimitri Kopriwa Apr 03 '20 at 12:15
13

Just restart your application in the server. It is a bug between spring and tomcat servers. Once the application restarts it consume a temp directory in the server.

Hasan Sawan
  • 391
  • 2
  • 14
  • 2
    What if that error on UAT or Production? we cannot restart this server again and again na. – Deva Jul 30 '19 at 08:52
  • 1
    As I mentioned above, the reason of this problem is , centOS will delete the temp dir frequently. When you application is running, but centOS deleted your temp dir, then there will be such error. So, restart your application can work for some time. But after some time, there will be that error again. – Mavlarn Aug 01 '19 at 04:02
7

This Issue was fixed a couple of days ago.
Spring Boot: 2.1.4 or 1.5.20

This version bump fixes an issue when the tmp dir was deleted
by the OS and the spring boot app tries to handle a multifile
upload.

Issue: https://github.com/spring-projects/spring-boot/issues/9616

https://github.com/MeiSign/Copy-Pasta/commit/1200fb353a48a3d0c92038dee7cced7cebf3acfe

Frankstar
  • 306
  • 1
  • 3
  • 10
6

We've had this problem since long too, I just wanted to eloborate some stuff relating to 2) in above accepted answer.

So, the problem here is that tomcat's temp folders suddenly "disappears" and not for "POSTs in general" as is claimed but for multipart requests specifically. Thus

spring.servlet.multipart.location/spring.http.multipart.location

is involved here. As @Frankstar said above, in recent spring-boot code this is fixed by "always creating the tmp-folder if it's not there", works too of course if you're running a super-fresh spring-boot.

You can, as suggested as in the accepted answer, point it to somewhere else other than /tmp and it will work fine (though, regarding cleanup you should perhaps have a read here https://github.com/spring-projects/spring-boot/issues/9983 - you are now reliant on spring-boots cleanup which, though, should work fine).

But why did the folder actually disappear? Further down @Hasan Sawan says that "It is a bug between spring and tomcat servers". But is it really..?

For us the solution was to configure this stuff. OSes such as CentOS will use (see for instance https://www.thegeekdiary.com/centos-rhel-7-how-tmpfiles-clean-up-tmp-or-var-tmp-replacement-of-tmpwatch)) systemd for cleaning up /tmp - and anything not accessed within 10 days will be cleaned by the default setting.

Thus on our redhat servers we solved this be editing

/usr/lib/tmpfiles.d/tmp.conf

adding a line like

X /tmp/tomcat.* 

to solve this issue. You can verify this too using

# SYSTEMD_LOG_TARGET=console SYSTEMD_LOG_LEVEL=debug /usr/bin/systemd-tmpfiles --clean 2>&1 | grep tomcat 

where you will see that these directories will now be ignored.

There is also this fix for systems whereas tmpwatch is used instead https://javahotfix.blogspot.com/2019/03/spring-boot-micro-services-tmptomcat.html

Note : the solutions mentioned above to "restart" or to just # mkdir /tmp/tomcat.... were simply not accepted where I work.

Ola Aronsson
  • 411
  • 4
  • 7
2

Question has already been answered, but maybe I can help someone out. I had this problem as well, but none of the suggested solutions worked for me.

We use Spring boot in combination with Zuul, which boiled down to the following:

  1. Stop the application
  2. Stop Zuul
  3. Remove tomcat related folders in the /tmp folder (this is where our tomcat folders were stored, might be different for others)
  4. Restart Zuul
  5. Restart the application

Simply restarting the application did not work for us, as it was pointing to a non-existing folder: the name was cached somewhere.

When using Zuul, the request go through Zuul first and throw exception there.

APPLE46
  • 3
  • 3
Edwin Lambregts
  • 408
  • 6
  • 22
  • Agreed, In micro services architecture, problem can be due to Zuul. I faced the same issue and tried everything above discussed but did not work. After I increased timeout with dfs-bulk-service.ribbon.ReadTimeout=90000 configuartion in Zuul properties, it worked fine. – Rajdeep Mar 07 '19 at 09:14
  • Note that the 'dfs-bulk-service' in the above comment is the actual service name, which will be different for you. Ref: https://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html – nanospeck Jan 06 '20 at 03:27
1

What I did to solve the issue was to relaunch the application adding -java.tmp.dir=/path/to/application/temp/ and creating a /temp/ folder in my application folder.

Dharman
  • 30,962
  • 25
  • 85
  • 135
user3450862
  • 379
  • 1
  • 6
  • 22
0

In micro services architecture, problem can be due to Zuul timeout. I faced the same issue and tried everything above discussed but did not work. After I increased timeout with dfs-bulk-service.ribbon.ReadTimeout=90000 configuartion in Zuul properties, it worked fine. Here dfs-bulk-service is my micro service name configured with Zuul as api gateway.

Rajdeep
  • 270
  • 2
  • 11
  • Note that the 'dfs-bulk-service' in the above answer is the actual service name, which will be different for you. Ref: https://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html – nanospeck Jan 06 '20 at 03:27
0

You maybe encode the form body of the POST request by Content-Type: multipart/form-data http header .

You should send a Content-Type: application/x-www-form-urlencoded POST

Green Lei
  • 3,150
  • 2
  • 20
  • 25
0

For me it was using the correct dependency (if using java/maven)

       <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
Llama
  • 465
  • 1
  • 8
  • 20
0

check the folder in the C:/ if is not there one folder with name temp than create it C:/temp ,,,this solution worked for me

m Piroli
  • 333
  • 3
  • 6