In this page

Configuring app logging

When investigating a run-time problem, you may need to increase the logging level for the Better Excel Exporter app. Doing so, it will write more details about what it does to the log, which helps you understand the problem.

How to enable DEBUG-level logging

To turn on DEBUG logging, just append the text "__DEBUG" to the view's name and create a new export. For example, rename "Excel (Current Fields)" to "Excel (Current Fields)__DEBUG".

Now execute the app function that you think fails, and check the log for the details.

How to enable cell-level logging

Sometimes during troubleshooting you need see what is inserted to what cell and what beans are available in the rendering context at that moment. This is where cell-level logging helps.

To turn on cell-level logging, just turn on DEBUG-level logging and it will automatically activate the cell-level one, too.

From now, two lines will be written to the log for each cell. One before processing the cell:

Processing cell "Issue Navigator!A5" (issue=..., column=...) with old value: ... (beans: ...)

...and one after that:

Cell "Issue Navigator!A5" set to new value: ...

Please note that if the output file is rendered to N cells, then cell-level logging alone will produce 2*N log lines! Therefore, remember to turn it off if it is not needed any longer.

Viewing the log

The Better Excel Exporter app writes its own log lines to a secure cloud-hosted log. It can be viewed through the app's user interface:

  1. Go to AppsBetter Excel ExporterView Log.
  2. If you can't see any log line written by the app, check if DEBUG logging is configured correctly, then use the corresponding app function again.

If you can't interpret the log lines you found, report it to our support. We are there to help you!


This section gives you practical hints to find the root cause when investigating problems in Excel templates and Groovy scripts.

Reduce data

If you see a problem that occurs when exporting a large data set, it is hard to find the precise root cause because of the sheer volume of data. Does it occur for every issue, for Story-type issues only or for the issue FOO-123 only? Similarly, does it occur for every field, for date-type fields only or for the "Due date" field only?

The following techniques help you re-produce a problem with a smaller scope, what is key to find the solution.

Reduce issues

It is helpful when the problem is related to one or more specific issues.

It's a simple idea that you can apply in several ways:

  • If you fail to export a large number of issues, export only the first one! If it fails as well, then you have a single issue to reproduce the problem. To verify if the problem appears for any issue, repeat the test using a few other randomly chosen issues.
  • Or, if you see the problem with a smaller number of issues, start removing issues one by one (or in small batches) and repeat the test after each removal. If the problem disappears, then it is caused by the most recently removed issue (batch).
  • Or, the previous technique in reverse direction: start adding issues one by one (or in small batches) and repeat the test after each addition. If the problem appears, then it is caused by the most recently added issue (batch).
  • Or, find a single or small number of problematic issues in a large dataset with "bisection":
    1. Split up the issues to two similarly-sized partitions (using JQL, for example).
    2. Test with the first partition.
    3. Test with the second partition.
    4. If the problem appears only with one of the partitions, then split that partition again, test those two halves again, and so on.
    5. Repeat this until you have a small scope.

These can be used in combination, be creative!

Reduce fields

It is helpful when the problem is related to a specific field.

The idea is the same as reducing the number of issues, but with fields. Basically, you just systematically add or remove fields and repeat the test until you reach a small scope that reproduces the problem. (You can add or remove fields to the Excel export typically by adding and removing columns in the Issue Navigator.)

Reduce features

It is helpful when the problem is related to a specific feature (e.g. exporting comments).

Obviously, disable the suspicious feature and test. If the problem disappears, then it is caused by that feature.

Reduce code

It is helpful when the problem is related to a specific code part in the Excel template or in the Groovy script.

Comment out the code part and test. If the problem disappears, then it is caused by that code part.

Other troubleshooting techniques

Advanced techniques in this section can give further help find problems in Groovy code.

Using getter-based expressions instead of property-based ones

Although these are identical when they succeed, the template expression that uses the getter method name may show more details about a problem than its property name based equivalent. Therefore, if you have a problem in the method that calculates the value "baz", replace ${fooBar.baz} with ${fooBar.getBaz()}.

Stopping on expression evaluation errors

By default, the Excel renderer is forgiving in the following situations:

  1. The expression ${fooBar.baz} cannot be evaluated, either because the object fooBar does not exist or it has no property baz.
  2. The expression ${fooBar.getBaz()} cannot be evaluated, either because the object fooBar does not exist or it has no method getBaz() or the method getBaz() throws an exception.

"Forgiving" above means that the expression is evaluated to an empty cell, but the problem remains hidden. In production use, it is useful because you can successfully export the Excel file and all non-affected parts will be correct. In troubleshooting, it is not useful because you can't see the problem.

To make it more useful for your troubleshooting session, enable DEBUG-level logging. It that mode, these errors will immediately terminate the export and the stack trace will be visible in the exported Excel spreadsheet.

Wrapping problematic code in a try-catch block

When you have a problematic code block, used through a template expression like ${fooBar.getBaz()} or ${fooBar.baz} and it mysteriously breaks the export, wrap it in a try-catch block!

See this example (that deliberately throws an exception to demonstrate "problematic code"):

fooBar = new FooBarTool(logger: logger)

class FooBarTool {
	def logger

	def getBaz() {
		try {
			throw new NullPointerException() // <- this is here just to demonstrate the technique

			// ... problematic code comes here

		} catch (Exception ex) {
			return ex.message

Why does it help in troubleshooting?

  1. The exception will be caught, but the export will not stop!
  2. The exception will be written to the log.
  3. The exception message will be returned to the template. It will appear exactly where the actual value should, giving you a "very visual" way of locating the problem.

Typical problems and their solutions

Groovy-related problems

I get MissingPropertyException or MissingMethodException in a Groovy script.

These may happen when you try to access a private or protected symbol (property or method) on a Java class.

Although the Groovy language is designed to be permissive when it comes to access control (meaning that it ignores the private and protected keywords in many scenarios), the Better Excel Exporter app uses an extended access control implementation that guarantees higher level of security. It guards against malicious Groovy scripts by "sandboxing" the Groovy code within the JVM.


class Foo {
	private def privateProperty = "PRIVATE_PROPERTY"

	private def privateMethod() {}

class Bar extends Foo {
	def accessPrivateProperty() {
		// throws groovy.lang.MissingPropertyException:
		// No such property: privateProperty for class: Bar

	def accessPrivateMethod() {
		// throws groovy.lang.MissingMethodException:
		// No signature of method: Bar.privateMethod() is applicable for argument types: ()

// throws org.codehaus.groovy.control.MultipleCompilationErrorsException:
// The class 'Baz' has an incorrect modifier private.
private class Baz {}

To fix the problem, your code must respect the access modifier rules:

  • If the protected or private symbol is in your Groovy script, change that to public. (You can just remove the access modifier, as the default visibility in Groovy is public.)
  • If it isn't, check the documentation (Javadoc) of the symbol and its encompassing class to see if there are public alternatives.
I get MissingPropertyException, MissingMethodException or CacheAccessControlException in a Groovy script.

These may happen when you try to work with a blacklisted Java class that is disallowed to use.

Note that importing a blaclisted class is possible, but the first time when you try to "actually work" with it (instantiate it, access its properties, call its methods, etc.), an exception like this will be thrown:

java.lang.RuntimeException: org.apache.velocity.exception.MethodInvocationException:
	Invocation of method 'getBar' in class FooTool threw exception org.codehaus.groovy.reflection.CacheAccessControlException:
Caused by: org.codehaus.groovy.reflection.CacheAccessControlException:
	Groovy object can not access method getBaz cacheAccessControlExceptionOf class com.acme.BazBuilder with modifiers "public static"
Caused by: access denied ("java.lang.reflect.ReflectPermission" "suppressAccessChecks")

It means that the getBar() method in your FooTool Groovy class tries to call com.acme.BazBuilder.getBaz(), but the com.acme.BazBuilder class is disallowed.

In the background, the Better Excel Exporter app checks each class against a blacklist. It guards against malicious Groovy scripts by limiting the classes available for the Groovy code.

To fix the problem, do not use the disallowed class! (It is disallowed for a good reason.) Find an alternative that is allowed, or replace it by writing the corresponding logic your in Groovy script.

I see the "Cannot open PivotTable source file..." error when I open the exported Excel file.

This problem can happen when the export contains a pivot table or pivot chart. Pivot tables and pivot charts have a reference to the input named range. If this reference is prefixed with the template's(!) filename and the output filename is different (which is very likely), then the reference is broken in the output file. We noticed that sometimes Excel is trying to be smart and inserts that prefix in the background for whatever reason.

To solve this, follow these steps:

  1. Open your template in Excel.
  2. Go to FileInfo screen.
  3. Click the Allow this information to be saved in your file link under Inspect Workbook section.
  4. Click inside a pivot table.
  5. Select Pivot Table ToolsAnalyzeChange Data Source.
  6. If the Table/Range field contains the filename as prefix, remove that (e.g. change 'my-template.xlsx'!issues to issues).
  7. Repeat the previous steps for all pivot tables.
  8. Save the file.
  9. Upload the file to your templates in Jira.
  10. Try another export.

Other problems

I see "Quota reached!" and "Hardly any quota left!" messages.

Jira data exports are resource-intensive tasks in general. Even more so, if they require extensive network communication between the Jira Cloud app and the Jira REST API, or if they execute computation-heavy Groovy scripts. To protect resources, Better Excel Exporter implements a quota system.

In the quota system, two factors are limited:

  1. the number of exports made within an hour
  2. the total duration of exports made within an hour

It means that you can run long export tasks, but less frequently, or short export tasks, but continuously. The app notifies you when you are near to the end of your quota to avoid bad surprises. If you eventually run out of quota, you just have to wait until the next hour and try again.

Important: please note that paid licenses enjoy a much larger quota than evaluation ones! It is because by paying the subscription fee (after the evaluation period is over), you help us in paying the AWS operational costs, which in turn allows us offer you a larger quota.


Ask us any time.