system.dataset.toExcel() java.io.IOException: Permission denied

xls = system.dataset.toExcel(True, self.custom.data )
system.perspective.print(xls)
system.perspective.download('data.xls',xls)

simple enough code on a perspective button that gives:
java.io.IOException: Permission denied

i tested this on another 8.1.15 server (same as the one with the error) and it works, so its something to do with the user permissions, but was wondering if anyone had any ideas of what permission is failing

server is linux

1 Like

The error should tell you what line number. Narrow it down for us.

heh I was working to get the full error but you’re too fast ;D

com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 2, in runAction at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:688) at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:705) at com.inductiveautomation.ignition.common.util.excel.adapters.DatasetExcelAdapter.drawSheet(DatasetExcelAdapter.java:61) at com.inductiveautomation.ignition.common.util.excel.adapters.DatasetExcelAdapter.drawWorkbook(DatasetExcelAdapter.java:44) at com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities.dataSetToExcelBytes(DatasetUtilities.java:1206) at com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities.toExcel(DatasetUtilities.java:1020) at jdk.internal.reflect.GeneratedMethodAccessor340.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) java.lang.RuntimeException: java.lang.RuntimeException: java.io.IOException: Permission denied
at org.python.core.Py.JavaError(Py.java:547)
at org.python.core.Py.JavaError(Py.java:538)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:192)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:208)
at org.python.core.PyObject.__call__(PyObject.java:477)
at org.python.core.PyObject.__call__(PyObject.java:481)
at org.python.pycode._pyx887.runAction$1(:4)
at org.python.pycode._pyx887.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyFunction.function___call__(PyFunction.java:474)
at org.python.core.PyFunction.__call__(PyFunction.java:469)
at org.python.core.PyFunction.__call__(PyFunction.java:464)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:831)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:813)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:806)
at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:994)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:871)
at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:137)
at com.inductiveautomation.perspective.gateway.action.ScriptAction.runAction(ScriptAction.java:71)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.lambda$call$0(ActionCollection.java:263)
at com.inductiveautomation.perspective.gateway.api.LoggingContext.mdc(LoggingContext.java:54)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:252)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:221)
at com.inductiveautomation.perspective.gateway.threading.BlockingTaskQueue$TaskWrapper.run(BlockingTaskQueue.java:154)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at com.inductiveautomation.perspective.gateway.threading.BlockingWork$BlockingWorkRunnable.run(BlockingWork.java:42)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.python.core.PyException: java.lang.RuntimeException: java.lang.RuntimeException: java.io.IOException: Permission denied
... 31 common frames omitted
Caused by: java.lang.RuntimeException: java.io.IOException: Permission denied
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:688)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:705)
at com.inductiveautomation.ignition.common.util.excel.adapters.DatasetExcelAdapter.drawSheet(DatasetExcelAdapter.java:61)
at com.inductiveautomation.ignition.common.util.excel.adapters.DatasetExcelAdapter.drawWorkbook(DatasetExcelAdapter.java:44)
at com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities.dataSetToExcelBytes(DatasetUtilities.java:1206)
at com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities.toExcel(DatasetUtilities.java:1020)
at jdk.internal.reflect.GeneratedMethodAccessor340.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)
... 28 common frames omitted
Caused by: java.io.IOException: Permission denied
at java.base/java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.base/java.io.File.createTempFile(Unknown Source)
at org.apache.poi.util.DefaultTempFileCreationStrategy.createTempFile(DefaultTempFileCreationStrategy.java:110)
at org.apache.poi.util.TempFile.createTempFile(TempFile.java:66)
at org.apache.poi.xssf.streaming.SheetDataWriter.createTempFile(SheetDataWriter.java:88)
at org.apache.poi.xssf.streaming.SheetDataWriter.(SheetDataWriter.java:71)
at org.apache.poi.xssf.streaming.SheetDataWriter.(SheetDataWriter.java:76)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheetDataWriter(SXSSFWorkbook.java:342)
at org.apache.poi.xssf.streaming.SXSSFSheet.(SXSSFSheet.java:80)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:684)
... 37 common frames omitted

Looks like the Apache POI library is trying to make a temp file for that operation. Do you have a writable /temp (or wherever) for your service?

thanks! it ended up being a few folders in the /tmp directory (not in the ignition directory, at the root) that had some folders with the wrong user permissions. now its working.

Good afternoon.

I have had the same issue on version 8.1.21, on a Linux server.
When executing the system.dataset.toExcel() function, the error you can see at the bottom occurs.
It seems that it is a known issue in other systems that use Java:

I was able to fix it by changing the permissions of the "/tmp/pofiles" folder:
image

sudo chmod 777 poifiles

The original permissions were these (ls -l):

drwxr-xr-x 2 ignition ignition 4096 Oct 13 12:27 pofiles

And current permissions are:
image

I don't know if my solution is the best one.
I'm also not sure why the issue was occurring. Can it be that the user who installed Ingition (root) is not the same as the owner (ignition) of the folder "/tmp/poifiles" ?

@pturmel
Can you tell us what would be the best solution, please?


Error that occurred before changing permissions:

Best Regards.

What user is running the Ignition service? (via systemctl status)

Perhaps your server is using SELinux or AppArmor?

systemctl status (command):

AppArmor or SELinux has not been installed. The problem started after updating Ignition 8.1.9 to 8.1.21.

Best Regards.

I'm going to guess that the Apache POI jars included in Ignition were updated and the temp file behavior changed. Consider opening a support ticket. But in the meantime, altering permissions seems to be a reasonable work-around.

Consider including the sticky bit in the folder permissions (I can't remember the precise combination) to avoid cross-user /tmp/ attacks. Also ensure that /tmp is mounted noexec.

The best solution would probably be to set the java.io.tmpdir system property, such as in the wrapper.java.additional parameters in the ignition.conf file; something like:
wrapper.java.additional.X=-Djava.io.tmpdir=path/to/directory

Apache POI will automatically use this new temp directory.

If you just want to override POI's behavior, you can do it programatically:

from org.apache.poi.util import TempFile, DefaultTempFileCreationStrategy
from java.util import File

dir = "some/new/directory"
TempFile.setTempFileCreationStrategy(DefaultTempFileCreationStrategy(File(dir)))
1 Like

@pturmel
@PGriffith

Thanks.