Thumbnails do not generate in Jira running in Azure

Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.

Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

Summary

Problem

When attaching a file to a JIRA issue thumbnails don't generate for certain image attachments (PNG, GIF).

The following appears in the atlassian-jira.log

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 Unable to create thumbnail /mnt/azure/jira-shared/data/attachments/ATL/10000/ATL-7305/thumbs/_thumb_668420.png1619809562911650984.tmp for image ATL.jpeg id: 668420, found in issue ATL-7305. Resetting thumbnailable flag to FALSE java.io.IOException: Unable to set the last modification time for /mnt/azure/jira-shared/data/attachments/ATL/10000/ATL-7305/thumbs/_thumb_668420.png1619809562911650984.tmp at org.apache.commons.io.FileUtils.touch(FileUtils.java:392) at com.atlassian.jira.issue.thumbnail.DefaultThumbnailManager.createThumbnail(DefaultThumbnailManager.java:206) at com.atlassian.jira.issue.thumbnail.DefaultThumbnailManager.doGetThumbnail(DefaultThumbnailManager.java:173) at com.atlassian.jira.issue.thumbnail.DefaultThumbnailManager.getThumbnail(DefaultThumbnailManager.java:129) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ... 2 filtered at java.lang.reflect.Method.invoke(Method.java:498) at com.atlassian.jira.config.component.SwitchingInvocationHandler.invoke(SwitchingInvocationHandler.java:22) at com.sun.proxy.$Proxy17.getThumbnail(Unknown Source) at com.atlassian.jira.issue.fields.rest.json.dto.AttachmentViewDtoConverterImpl$1.apply(AttachmentViewDtoConverterImpl.java:101) at com.atlassian.jira.issue.fields.rest.json.dto.AttachmentViewDtoConverterImpl$1.apply(AttachmentViewDtoConverterImpl.java:74) at com.google.common.collect.Iterators$8.transform(Iterators.java:799) at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:48) at com.google.common.collect.ImmutableCollection$Builder.addAll(ImmutableCollection.java:281) at com.google.common.collect.ImmutableCollection$ArrayBasedBuilder.addAll(ImmutableCollection.java:360) at com.google.common.collect.ImmutableList$Builder.addAll(ImmutableList.java:665) at com.atlassian.jira.issue.fields.rest.json.dto.AttachmentViewDtoConverterImpl.convert(AttachmentViewDtoConverterImpl.java:147) at com.atlassian.jira.issue.fields.rest.json.dto.AttachmentViewDtoConverterImpl.convert(AttachmentViewDtoConverterImpl.java:41) ... 2 filtered at java.lang.reflect.Method.invoke(Method.java:498) at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26) at com.sun.proxy.$Proxy515.convert(Unknown Source) ... 2 filtered at java.lang.reflect.Method.invoke(Method.java:498) at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:136) at com.sun.proxy.$Proxy515.convert(Unknown Source) at com.atlassian.jira.plugins.dnd.attachment.rest.AttachmentResource.attachTemporaryfile(AttachmentResource.java:118) ... 3 filtered at java.lang.reflect.Method.invoke(Method.java:498) at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) ... 12 filtered at com.atlassian.plugins.rest.module.RestDelegatingServletFilter$JerseyOsgiServletContainer.doFilter(RestDelegatingServletFilter.java:154) ... 1 filtered at com.atlassian.plugins.rest.module.RestDelegatingServletFilter.doFilter(RestDelegatingServletFilter.java:68) ... 37 filtered at com.atlassian.web.servlet.plugin.request.RedirectInterceptingFilter.doFilter(RedirectInterceptingFilter.java:21) ... 53 filtered at com.atlassian.jira.security.JiraSecurityFilter.lambda$doFilter$0(JiraSecurityFilter.java:66) ... 1 filtered at com.atlassian.jira.security.JiraSecurityFilter.doFilter(JiraSecurityFilter.java:64) ... 16 filtered at com.atlassian.plugins.rest.module.servlet.RestSeraphFilter.doFilter(RestSeraphFilter.java:37) ... 19 filtered at com.atlassian.jira.servermetrics.CorrelationIdPopulatorFilter.doFilter(CorrelationIdPopulatorFilter.java:30) ... 10 filtered at com.atlassian.web.servlet.plugin.request.RedirectInterceptingFilter.doFilter(RedirectInterceptingFilter.java:21) ... 4 filtered at com.atlassian.web.servlet.plugin.LocationCleanerFilter.doFilter(LocationCleanerFilter.java:36) ... 26 filtered at com.atlassian.jira.servermetrics.MetricsCollectorFilter.doFilter(MetricsCollectorFilter.java:25) ... 23 filtered at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)

Diagnosis

Environment

  • Instance is hosted in Microsoft Azure (Linux VM, file share)

  • Jira home directory (or shared-home, for Data Center instances) is an Azure file share, mounted to a folder in the VM

  • Mount options are set with the default user ID and group ID options:

    uid=0, noforceuid, gid=0, noforcegid

Diagnostic Steps

  • The actual attachments can be viewed and accessed as expected

  • The thumbnails folder in the home directory may contain thumbnail files with 0-length

  • Files and folders in the home/shared-home directory are owned by root/root

  • Check the mount options with sudo mount | grep cifs

Cause

Using the default mount options to lock the gid and uid, thereby resulting in root/root owning all of the files and folders in the mount directory, somehow prevents the thumbnails from being generated.

Solution

Resolution

There are two ways to resolve this:

Resolution 1

Re-configure the mount options to set the uid and gid specifically to the user (and the user's group) that runs the application. For example, if you have a dedicated user called jira and it's in a group called jira, you will set uid=jira and gid=jira in your mount options.

Resolution 2

Add "noperm" to the mount options. An /etc/fstab entry with noperm would look something like this:

1 2 //testesourceroupdiag.file.core.windows.net/testazurefs /home/testazure/atlassian/shared-home cifs noperm,nofail,vers=3.0,credentials=/etc/smbcredentials/testesourceroupdiag.cred,file_mode=0777,dir_mode=0777,serverino
Updated on April 15, 2025

Still need help?

The Atlassian Community is here for you.