Can make a folder in a gateway script but cannot create report in folder?

I have a gateway message handler to create PDF’s. It makes new folders and then creates a PDF report and puts it inside of one of those folders. Here are the relevant parts -

	try:
		new_folders.create.folder(destinationPath)
	except OSError:
		logger.info("folder already created")
		pass
	
	# ******* CREATE PDF QUOTE ******* #
	try:
		system.report.executeAndDistribute(path=reportPath, project="PSM4_Project", action="save", parameters=overRides, actionSettings=settings)
		status = True
		Message = "Successfully uploaded PDF!"
	except:
		logger.info("ERROR: ")
		status = False
		Message = Message + str(sys.exc_info()[0]) + " | " + str(sys.exc_info()[1])
		logger.info("ERROR: " + str(Message))

        logger.info('here 9')
	project = "PSM4_Project"
	logger.info('here 10')
	messageHandler = "handleSaveQuoteResponse"
	logger.info('here 11')
	parameters = {'ClientSessionID': ClientSessionID, 'Message': Message}
	logger.info('here 12')
	results = system.util.sendMessage(project,messageHandler,parameters,scope="C")

Now I am able to make the folders with the new_folders.create.folder() script and that works. But then my system.report.executeAndDistribute failes, and then also the Message variable is always

“Successfully uploaded PDF!” even when the system.report.executeAndDistribute line fails which is confusing me as well, and then I get the error message sent to the client. So it seems like this gateway message handler is sending two messages back to the client, first with the message “Successfully uploaded PDF!” and then again with the sys.exc_info() from the except clause.

I turned on Trace for Reporting Module in the gateway logs and this is what I see

Data	23Mar2021 10:02:00	[projectName=PSM4_Project,reportPath=Quote_Time_Material 0] Could not create directory P:\Heerema\Hawthorne, NJ\L'Oreal - Clark\Filling Line 1 Kalix Service, 7098\Quotes\ in SaveAs Action Save File
java.io.IOException: Unable to create directory P:\Heerema\Hawthorne, NJ\L'Oreal - Clark\Filling Line 1 Kalix Service, 7098\Quotes

at org.apache.commons.io.FileUtils.forceMkdir(FileUtils.java:2211)

at com.inductiveautomation.reporting.gateway.actions.SaveFileReportAction.perform(SaveFileReportAction.java:91)

at com.inductiveautomation.reporting.gateway.actions.SaveFileReportAction.perform(SaveFileReportAction.java:148)

at com.inductiveautomation.reporting.gateway.scripting.GatewayScriptingFunctions.lambda$executeAndDistribute$1(GatewayScriptingFunctions.java:197)

at com.inductiveautomation.reporting.gateway.ReportingGatewayHook.executeReport(ReportingGatewayHook.java:305)

at com.inductiveautomation.reporting.gateway.scripting.GatewayScriptingFunctions.executeAndDistribute(GatewayScriptingFunctions.java:188)

at com.inductiveautomation.reporting.common.scripting.ReportScriptingFunctionsPyWrapper.executeAndDistribute(ReportScriptingFunctionsPyWrapper.java:77)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.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:188)

at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction.__call__(ScriptManager.java:524)

at org.python.core.PyObject.__call__(PyObject.java:413)

at org.python.pycode._pyx84.handleMessage$1(:124)

at org.python.pycode._pyx84.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:171)

at org.python.core.PyBaseCode.call(PyBaseCode.java:308)

at org.python.core.PyFunction.function___call__(PyFunction.java:471)

at org.python.core.PyFunction.__call__(PyFunction.java:466)

at org.python.core.PyFunction.__call__(PyFunction.java:461)

at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:822)

at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:806)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:687)

at com.inductiveautomation.ignition.common.script.message.MessageHandlerRunnable.run(MessageHandlerRunnable.java:114)

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.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

It says it’s a file not found exception, but I don’t know how that’s possible since I just made the folder it’s supposed to go in, and if I copy/paste the folder location from the gateway and put it into a file explorer, it does exist.

After my client sends the gateway message, it gets two responses -
image
and then

Any insights would be helpful. Thanks

Unable to create directory P:/
That drive letter seems real suspicious to me. How does new_folders.create.folder() address that path? What are destinationPath and reportPath?
It seems likely that the two different mechanisms are accessing a (theoretically identical) location in different ways, and that’s leading to the problems.

Here is new_folders.create.folder()

def folder(path):
	"""
	Creates path, perhaps with additional logic needed at some point for intermediary paths.
	Args:
		path: string, what path do we want to create
	Returns:
		None
	"""
	import os
	try:
		os.mkdir(path)
	except OSError:
		raise OSError("Failed to create path %s"%(path))

And here is the entire gateway script (content warning: ugly code)

	import os
	import sys
	import string
	import time
	import datetime
	import re
	import system
	import shutil
	import new_folders
	logger = system.util.getLogger("regex log")
	
	Message = "::GATEWAY:: "
	tid = ""
	logger.info("payload: " + str(payload))
	ClientSessionID = payload['ClientSessionID']
	QuoteNum = payload['QuoteNum']
	QuoteRev = payload['QuoteRev']
	QuotePath = payload['QuotePath']
	QuoteNamePDF = payload['QuoteNamePDF']
	logger.info("QUOTE NAME PDF" + str(QuoteNamePDF))
	QuoteAddress = payload['QuoteAddress']
	QuoteProjDesc = payload['QuoteProjDesc']
	pattern = re.compile('\s\d+.00')
	
	for wholeHour in re.findall(pattern, QuoteProjDesc):
		partToKeep = wholeHour.split('.')[0]
		logger.info('part to keep:'+str(partToKeep))
		logger.info("whole Hour:" + str(wholeHour))
		QuoteProjDesc = QuoteProjDesc.replace(wholeHour, partToKeep)
	QuotePathTemp = r'C:\Ignition Reports'
	PathSource = r'C:\Ignition Reports'
	reportPath = payload['reportPath']
		
	logger.info("reportPath " + str(reportPath))
	logger.info("QuoteTempPath " + str(QuotePathTemp))
	logger.info("QuoteNamePDF " + str(QuoteNamePDF))
	# ******* SETUP QUOTE VARIABLES ******* #
	overRides = {'QuoteNum' : QuoteNum, 'RevisionNum' : QuoteRev, 'QuoteAddress': QuoteAddress, 'ProjectDescription' : QuoteProjDesc}
	logger.info("overrides: " + str(overRides))
	destinationPath = str(QuotePath + "\\").replace('/','\\')
	settings = {"path":destinationPath, "fileName":QuoteNamePDF, "format":"pdf"}
	logger.info("settings: " + str(settings))
	
	try:
		new_folders.create.folder(destinationPath)
	except OSError:
		logger.info("folder already created")
		pass
	
	# ******* CREATE PDF QUOTE ******* #
	try:
		system.report.executeAndDistribute(path=reportPath, project="PSM4_Project", action="save", parameters=overRides, actionSettings=settings)
		status = True
		Message = "Successfully uploaded PDF!"
	except Exception, e:
		logger.info("ERROR: " + str(e))
		status = False
		Message = Message + str(sys.exc_info()[0]) + " | " + str(sys.exc_info()[1])
		logger.info("ERROR: " + str(Message))
	
	
	# ******* SEND SUCCESS OR FAILURE MESSAGE TO CLIENT ******* #
	logger.info('here 9')
	project = "PSM4_Project"
	logger.info('here 10')
	messageHandler = "handleSaveQuoteResponse"
	logger.info('here 11')
	parameters = {'ClientSessionID': ClientSessionID, 'Message': Message}
	logger.info('here 12')
	results = system.util.sendMessage(project,messageHandler,parameters,scope="C")

The destinationPath is the path key here -
settings: {'fileName': u'Filling Line 1 Kalix Service, Quote 7098-1.pdf', 'format': 'pdf', 'path': "P:\\Heerema\\Hawthorne, NJ\\L'Oreal - Clark\\Filling Line 1 Kalix Service, 7098\\Quotes\\"}

and the reportPath is Quote_Time_Material 0