Dev Space

Customize & extend the power of Alteryx. SDKs, APIs, custom tools, and more!
The Expert Exam is now live online! Read about the specifics and what it took to bring it to life in the blog by our very own Elizabeth Bonnell!
SOLVED

Invalid package file when posting workflow to Gallery

Highlighted
10 - Fireball

I have run into another issue posting a workflow to my gallery.  I am able to push yxzp files, but I want to try pushing yxmd or yxwz files as well.  From what I can tell, yxzp files are simple zip files with all of the workflows/macros/assets bundled together.  However, when I create a zip file containing my yxmd and send it to the server, I keep getting response 400, "Invalid package file".  The stack trace from the gallery log looks like this:

 

2019-05-22 18:40:52.544007,ERROR,156,ErrorHandler,HandleError,,,,,,,,,,Exception caught by ErrorHandler and marshalled to client,"Alteryx.Cloud.Common.Exceptions.BadRequestException: Invalid package file.->   at Alteryx.Cloud.Engine.AppEngine.LoadWorkflowDocument(String documentXml)->   at Alteryx.Cloud.Engine.AppEngine.GetWorkflowsFromPackage(String packageFile)->   at Alteryx.Cloud.Models.Presenters.AdminApiPresenter.PublishApp(AppFileInfo fileInfo, ExecutionModeType runMode, Int32 validationPriority, String requestId)->   at Alteryx.Cloud.Models.Presenters.AdminApiPresenter.<PublishAppAsync>d__24.MoveNext()->--- End of stack trace from previous location where exception was thrown ---->   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()->   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)->   at Alteryx.Cloud.Server.Services.Api.AdminApiServiceV1.<PublishYxzp>d__10.MoveNext()->--- End of stack trace from previous location where exception was thrown ---->   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()->   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)->   at System.ServiceModel.Dispatcher.TaskMethodInvoker.<InvokeAsync>d__16.MoveNext()->--- End of stack trace from previous location where exception was thrown ---->   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()->   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)->   at System.ServiceModel.Dispatcher.TaskMethodInvoker.InvokeEnd(Object instance, Object[]& outputs, IAsyncResult result)->   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeEnd(MessageRpc& rpc)->   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage7(MessageRpc& rpc)->   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)"

 

 

The body of my request, containing the bytes of my generated zip file, looks like this:

 

b'--0e5d695af01618a37eea7a73d8103b0a\r\nContent-Disposition: form-data; name="file"; filename="TestNoMacro.yxmd"\r\n\r\nPK\x03\x04\x14\x00\x00\x00\x08\x00\xa0z\xb6N\xc8SK\x14\x80\x02\x00\x00\x91\x05\x00\x00\x10\x00\x00\x00testnomacro.yxmduT\xdb\x8e\xda0\x10\xfd\x15+\x1f@\xd8\xb6\x0f}\x08Y\xb1\x1bv\x8b\x04\x0b\x82h+\xf5\xa5\xf2&C\xb0\xeax"_X\xd2\xaf\xef8!\x04\x08}\xf2x\xce\\\xcf\x8c\x1d=\x1eK\xc9\x0e\xa0\x8d@5\t\x1eF\xe3\xe01\x8e\xa6\xd2\x82\xae\x8f\tf\xae\x04eY},\xf3w\xd0\x93\xe0\xcb\xf8\xe1\xfb\xe8[\x10Go\x98\x83i\x0f\x96"\xcay2\t\xbe\x92\xfe\xd5\x89-X+Ta\xd8Z\xbaBP\xd0S\xb4\'n\xa0U\x19\xb2\x1a\xa5p\xb4sU9\xdbK\xe4\xbfF#,\x95\xc2\x8eT\xcc\xf8K\xc0\xea\xf6\x0c\xe3(\xbc\x88M\x86\x1a+\xd0V\xf8*\x9eQ\xedD\xe14\xf7\x9eT\x94+7\xf8i\xd8\x81K\x07\xe4\xee\x9d_\x04\xc8\xdc\x9cN\xa6xI@#7h\xd8\xc1\t\xb7<\x8et\x1ce\xf14\n3BH\x0e[mx\x93f\xaa\x14\xdaFf\x890\x95\xe4\xf5\x92\xd8\x98\x04cO\x0f%\xa0\xb8\t\xec\xb8\x93\xb6\xb7\xf4\xad\x92~\x01;\xdb\x95\xf7\xc2\xa5\x81\xa6\x88\xde\x8c.\x97\xfd\xcd\x14\x91\x06g^\xdbk"\xe5=j[p\x94K\x19\xf4\x863eu\xbdF\xa1\xec\xd9\xa5\'\xdd\xa7\xf6s<\x1d-\x9f\n2_\x88\t\xaf\x99^B\x89\xbafy\xdb\xd7$H\xb5kj\x7f\x95\xf8\xc1\xe5\x062\xd4\xf9B\x94\xe2\xdc\xdd\xd8\xa3)\x94\xd5\x8b\x90`\x86\x8e\x17$\xfa\xfdk\xd4L\xa8L\xba\x1c\xfc^\xbd\xb5\x93\xea8\xa2\xca\x0e3\xadQ_%y\x18\x0f\xb1\xdf[\x8b\xd5\x80\xe3g\xae2\x90+\xd5\xd8\rP\x1a#\xff\x90\xf0\xa4i{`\x80\xce\x94\x07\xd7\xa0w\xa8K\x1f\x87\x88\xd9\tI#\xf9_\xa0\xa9\x94+g\x89\xe3\x81\xc1v\x8f\x9f\x84.y\xa6q\t\xc6\xf0\x02\xcc]\xa3~\x14[\xa2\xc9\x99\xb9Y\xa9\xce\xb0\xe3\xf0\x9e\xddJ\xc9\xfa\xe7\x1e\xd4\xc6)uQa\xe7\xf2\x0b\xb1\\\xc0\x01\xe4\xd5\x9c\x16\xbcFg\xd3\xba\x82\xf8\x07j\xf1\x17\x95\xe52\n/\xd4\xb4\x00\x96\xcf\xd5\x0e\xdb\x15\x9f\x1b?V/\xdd&\xf0\xba8\x05c\xdf\xb0i\x92v\xcbk\xe8E\x98L\x8b\xca\x17JV\x1bD\xdbM\xd9\xef\t\x89\xef\xedWt\xba\xcdU\xf2qg\x88\x16\nZ\xc3\x93\xd7\x16\xb8\xce\xf6)/\xfc\xb2N\x9d\xdd\xa3n\xb6\xa1\xac\xb8\xaa\x1b\xa9\xaa\xb5(\xf66\xbcJ\xbf\x10\xea\x0f\xe3\x99u\x9c\xdeQ\xc0\xf2\xf6\tCN\x17?\xec#/+9(\xd8\xb7\xeb\xdf\xcb\x19\x0e{Bf\x07\xfa*M\xb7\'\xf9-#a\x87_=\xed\xf0\xe6\xab\x8d\xff\x01PK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0z\xb6N\xc8SK\x14\x80\x02\x00\x00\x91\x05\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00testnomacro.yxmdPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00>\x00\x00\x00\xae\x02\x00\x00\x00\x00\r\n--0e5d695af01618a37eea7a73d8103b0a\r\nContent-Disposition: form-data; name="name"\r\n\r\nTest\r\n--0e5d695af01618a37eea7a73d8103b0a\r\nContent-Disposition: form-data; name="owner"\r\n\r\nusthlar@us.abb.com\r\n--0e5d695af01618a37eea7a73d8103b0a\r\nContent-Disposition: form-data; name="validate"\r\n\r\nfalse\r\n--0e5d695af01618a37eea7a73d8103b0a\r\nContent-Disposition: form-data; name="isPublic"\r\n\r\ntrue\r\n--0e5d695af01618a37eea7a73d8103b0a\r\nContent-Disposition: form-data; name="sourceId"\r\n\r\n\r\n--0e5d695af01618a37eea7a73d8103b0a\r\nContent-Disposition: form-data; name="workerTag"\r\n\r\n\r\n--0e5d695af01618a37eea7a73d8103b0a\r\nContent-Disposition: form-data; name="canDownload"\r\n\r\ntrue\r\n--0e5d695af01618a37eea7a73d8103b0a--\r\n'

 

 

I am generating the zip file using this Python code:

 

def zip_package(package: Dict[str, PackageFile]) -> bytes:
    zip_bytes = BytesIO()
    zip_file = zipfile.ZipFile(zip_bytes, mode="w", compression=zipfile.ZIP_DEFLATED, allowZip64=True)
    for key in package.keys():
        package_file = package[key]
        package_file_str = b"<?xml version=\"1.0\"?>" + ET.tostring(package_file.Xml, encoding="utf-8", method="xml")
        zip_file.writestr(package[key].Filename, package_file_str)
    zip_file.close()
    zip_bytes.seek(0)
    return zip_bytes.read()

 

 

Is my assumption that yxzp files are simple zip files accurate?  Or is there more to it?  Is there a particular zip algorithm I should be using?  The zip file my code generates can be opened in File Explorer and contains workflows which I am able to open in Designer, so I don't think it's a matter of my code creating a malformed workflow.

Highlighted
16 - Nebula
16 - Nebula

@tlarsen7572 For what it's worth, when I open a yxzp using 7-zip and then go to file >>> properties, there is a comment field that contains the exact name of the worflow inside the yxzp:

Capture.PNG

It seems like a stretch, but that would be one difference between your yxzp and a standard yxzp.

Highlighted
10 - Fireball

@patrick_digan, you sir, are awesome!  That is exactly what the problem was.

Highlighted
Alteryx Partner

Hi @tlarsen7572 & @patrick_digan,

 

we just ran into the same issue and got a 400 error response from POSTing a zipped yxmd into a yxzp.

The package was zipped by 7zip command line using zip deflate method.

 

Opening the package in Designer works fine but Server denies to accept the upload.

Adding the comment manually via 7zip interface doesn't work either 😞

What still looks different after commenting in comparison to the original yxzp is that the comment seems to sit on the yxmd file in the package and not the package file itself.  

 

Do you have any ideas what that could be?

 

Kind regards,

Sascha