spring-boot: Tomcat does not create temporary directory used to store file uploads when it does not exist

Steps to Reproduce When spring boot application starts with default value of server.tomcat.basedir in application.properties. It creates two folders in /tmp folder. /tmp/tomcat.xxxxx/.. and /tmp-docbase.xxxx/

These directories are used to save temp files during multipart upload among other needed functions. In production system such as Centos, by default system is configured to delete all /tmp files if not touched for 10 days. Once this file is deleted logs will show this error and upload will fail with following exception

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [**/tmp/tomcat.1220970741172837513.8080/work/Tomcat/localhost/ROOT]** is not valid
	at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:111)

Possible Solution: May be lets check if required temp directory doesn’t exist recreate during multipart upload. And upload will work without any additional settings. Other fixes/suggestions are welcome as well.

Affected Versions Logs are from Spring Boot v1.4.3.RELEASE but its still same in 1.5.3.RELEASE

Workarounds

  • On Centos 7 update tmp.conf in following three directories /etc/tmpfiles.d/, /run/tmpfiles.d/ and /usr/lib/tmpfiles.d/. with following line x /tmp/tomcat*

OR handle programmatically

  • Catch exception in GlobalException Handler and recreate directory and inform user to try upload again.

full_log.txt

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 14
  • Comments: 29 (11 by maintainers)

Commits related to this issue

Most upvoted comments

@dixgaurav You can see the list of releases that contain the fix in the commit that closed this issue. In the 2.1.x line it was fixed in 2.1.4.

As of Tomcat 9.0.17 and 8.5.39, Tomcat will have opt-in support for creating the necessary directories when saving an upload. We can use this issue to opt in and update the documentation.

@VitalieS Yes, the bug is still open. If you look at the very top of the issue there’s a little icon that tells you the current status.

@wilkinsona Okay. Thank you for the answer. By the way My app work properly now after a day after rebooting my app. I guess the directory was cached in somewhere … I posted my question in Stackoverflow. (https://stackoverflow.com/questions/50523407/the-temporary-upload-location-tmp-tomcat-4296537502689403143-5000-work-tomcat)

My program has no Multipart file upload task but it occurs error like:

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

why it occurs really make me confused!

Hi Kappmeier,

I didn’t get chance to look into spring boot code to find where this multipart exception is throw. But I handled it my GlobalExceptionHandler in following way. So when I detect that an upload failed because directory is deleted by system cleanup process. I just recreate it and ask user to try upload file again.

So in my humble opinion same check can be placed inside Spring Boot so if directory doesn’t exist, it should try to recreate. If it failed due to access rights only than upload should fail.

public  ResponseEntity<?> handle(org.springframework.web.multipart.MultipartException exception) {
		Log.error("handle->MultipartException" + exception.getMessage(),exception);
		// general exception
		if (exception.getCause() instanceof IOException && exception.getCause().getMessage().startsWith("The temporary upload location"))
		{
			String pathToRecreate = exception.getMessage().substring(exception.getMessage().indexOf("[")+1,exception.getMessage().indexOf("]"));
			Set<PosixFilePermission> perms = new HashSet<>();
		    // add permission as rw-r--r-- 644
		    perms.add(PosixFilePermission.OWNER_WRITE);
		    perms.add(PosixFilePermission.OWNER_READ);
		    perms.add(PosixFilePermission.OWNER_EXECUTE);	    
		    perms.add(PosixFilePermission.GROUP_READ);
		    perms.add(PosixFilePermission.GROUP_WRITE);
		    perms.add(PosixFilePermission.GROUP_EXECUTE);
		    FileAttribute<Set<PosixFilePermission>> fileAttributes = PosixFilePermissions.asFileAttribute(perms);
			try {			
				Files.createDirectories(FileSystems.getDefault().getPath(pathToRecreate), fileAttributes);
			} catch (IOException e) {
				LOG.error(e.getMessage(),e);
				return ResponseUtils.sendError("Unable to recreate deleted temp directories. Please check  "+ pathToRecreate);
			}	
			return ResponseUtils.sendError("Recovered from temporary error by recreating temporary directory. Please try to upload logo again.");		
		}
		return ResponseUtils.sendError("Unable to process this request.");
	}

Is it fully resolved?

Getting similar issue. I am reading input stream from MultipartFile and hitting another REST API in a loop. And initially for sometime it works fine but after some time it starts giving FileNotFoundException.

Let’s say, I am running loop for 10 times. So, for 6-7 times it works fine but after that it starts giving this error.

I am using spring boot version 2.4.5

Exception:- java.io.FileNotFoundException: /tmp/tomcat.8080.4399610540988131483/work/Tomcat/localhost/ROOT/upload_d04b3ab7_7d5b_405e_9a50_d0fe0a8c9e6f_00000000.tmp (No such file or directory)

I have also tried spring.servlet.multipart.location property to change default multipart file upload location. In this case, it creates new temporary location and works for some time initially but after some time it starts giving the same error. (Let’s say, I am running loop for 10 times. So, for 6-7 times it works fine but after that it starts giving FileNotFoundException. )

Any idea why am i getting this error ?

@ninezero90hy The issue is still open and there’s not been any progress made on implementing a solution.

@philwebb this doesn’t seem to be a duplicate can it be reopened? the other issues are about using another location and the danger of using /tmp

This one is about recreating the files if it can be detected that they have been deleted.