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
Was this helpful?