I found this post that was identical to my problem. https://community.retool.com/t/error-passing-values-to-multi-step-loop-block/54068. With one variation. I was not seeing the internal GUID you use as an ID (because as the post indicates you "fixed" it). However the symptoms presented exactly the same. After 4 hours of experimenting with simple workflows, i discovered that if I create the function first, specify it's parameters then create the loop object and use that function and specify what columns from my query to use as substitution (IE: {{value.client_email}} {{value.client_name}} {{value.location_info}}) it works fine. HOWEVER, if it change the function to another function or change the parameters (change the name add one, drop one) the substitution does not occur. After closer examination, i found the the meta data returned by the loop for every single call to the function for every record a message "function '{long guid}' not found". if I then delete the loop and recreate it, it runs fine. But any time i change the parameters (and I have not checked to see if it also occurs when i just change the function), it causes this error and I have to recreate the loop step. I suspect somewhere you are saving the function it's generating a new unique id and the link to the new unique id is not getting made to the loop object. I'm not certain what conditions are causing the function to have a new unique id - is it the collection of parameters or is it the collection of sub steps in the function?
workaround is just to drop the loop and recreate it - annoying and not huge - YET - however as our workflows increase in number and complexity - this is going to be problematic.
I believe safest way of dealing with an issue like this is to maintain full control over your loop block by using the JS Code loop runner instead of the automatic function options.
I'd also like to say that I feel like the issue you are experiencing is one of the (sadly) unfortunate consequences of how Retool Cloud development is currently implemented. I am sure that there is extensive Q&A that goes into rolling out many new features, but as you are seeing there are still some issues that make it out into the releases which end up falling on end users to catch as edge cases.
Currently, the only way to control the stable version releases from the user side is to implement an on-prem instance of Retool (AFAIK).
By JS Code Loop runner do you mean 1) implement a loop 2) use JS Code as the executor for each loop 3) call my multi-step function (named loop_steps) supplying the params for each record in the loop?
That is exactly what I mean, yes. Some additional benefits of loops using the JS Code executor is that you can customize your error response handling via try/catch and add in other custom properties to implement filters for how to behave after the loop.
ETA: the syntax for calling a function is a little different than the normal query.trigger({additionalScope {...}}) format. To call a function in the JS code you use let result = await functionName(param1, param2...)
I believe that you can also supply named parameters rather than providing them ordinally. functionName(id: param2, name: param1) kind of thing.
Thanks guys. I was actually able to get the loop control to work pretty well and reliably. The key is to not have a ton of paramaters you pass in. Rather i have just one parameter with a composite json block - ie record, where in any sub records (think invoice header and detail lines) is passed in with the record, and then extract whats needed within the function. This works extremely well because 1) i only have 1 parameter and thus when i define the loop it never really changes 2) before i call the loop i can call a record extractor to pull out one record and use that as the default value within the multi step function for testing - simple cut and paste 3) pasting that in as the default value when testing allows me to test multiple steps one at a time. I've build 4 fairly complex workflows to sync customers and send and finalize invoices in stripe and update the results in our DBS. This approach has worked EXTREEMLY well to identify the multiple "hidden features" with stripe, in a very short amount of time. While yes the JS code loop runner would give more control, it would be more maintenance intensive once i turn this over to a developer for maintenance. I like this approach for debugging, testing and production. I also like using the stripe resources defined in retool as it has the additional objects that can be specified and where they are a type, the valid types. Very productive. I could use the raw rest api approach but then i have to specify the header, auth code, etc and do housekeeping up front that the tool simplifies. The return object is also nice and predictable. When items fail in a loop, the failing reason is embedded as metta data object for the record that failed in the loop. Inspecting the indexes that have values against the return values i return, allow for quick identification of what went wrong, which combined with the testing approach I outlined earlier, allows me to very quickly identify which step of the multi-step function went wrong.
That's some really interesting insight, @David_Bolen! Thanks for sharing. I'll flag this to the owning team and do some additional testing of my own. As soon as there's something substantial to share, I'll provide an update here.