Coded workflows/source files: Pitfall list?

Hi,

Is there a pitfall/gotcha/known issues up to date list for Coded Workflows and/or Coded source files somewhere?
For 24.10.latest?

We’re having a lot of frustrations battling coded workflows in combination with coded source files to get them to work in even relatively simple projects.
Compilation race conditions, subnamespace issues, surprise name clashes, everything-runs-but-cant-publish (with no reasonable errors), studio breaking on workflow right-click, caching issues, activities that break “randomly” (looking at you foreach…) etc.
It’s extremely frustrating, and eats a ton of time from projects, especially when “it feels like every day” it’s a one step forward, two steps back situation. It’s getting to a point where we’re considering just banning coded workflows fully, as it’s seriously demoralizing to work with them.

And we’re not talking here about super complex code, but pretty basic stuff (I mean really C# 101 level). All code compiles, all workflows work on themselves, you clone a fresh copy from latest commit (or just get back to things the next day) and suddenly nothing works, because some hidden BS is getting in the way somewhere.

Yes, I’m irritated, and so are our other devs that dared to go into coded workflows. We’ve specifically waited a full year (23.10 → 24.10) before attempting anything “real” with coded workflows, and the results are severely dissapointing so far.
So I’m trying to at least get a list of things to look out for, as I’m not even that hopeful on them getting fixed for real (how many times was foreach “fixed” so far?).

Hi Andrzej,

I’m one of the engineering leads behind Coded Workflows and I’m sorry to hear that you’re experiencing issues with it.

In our team, we have several very large (500+ files) coded workflows projects built internally and are not seeing similar issues, however it may always be some specific functionality, non-standard NuGet package, or scenario that is triggering this unwanted behavior (especially race conditions, caching issues or Studio breaking).

We’d like to understand your situation a bit better, could you provide some reproducible examples that we can investigate? If this is not possible, perhaps we can schedule a call so we can more deeply understand your situation and help resolve your issues.

Thanks,
Alvin

1 Like

Hi Alvin,

We’ve filed a support ticket (02620600), the details are there for one of the projects that had a “culmination” of different issues and is now in a pretty broken state (to a point where we’re thinking of just recreating it piece by piece).

I’d be happy to jump into a call with that Dev and someone from your team to see what’s going on there.

Cheers,
Andrzej

I’ve found that they’ve become relatively stable, however there are for sure some pitfalls and things you need to consider.

Never rename your project after having coded workflows / source files and having them in templates just doesn’t really work properly (cause the project name changes).

Always always make a constructor in a coded source file. If you don’t have a constructor in a coded source file they Studio can and will freak out at you at some point.
Even if its an empty constructor, make one.

After that, maybe you can be more specific on any issues and some of us can share tips for how we work around it or if we do things differently to not hit it.

@AlvinStanescu its easy to get only negative feedback. Let me say, the coded source files in particular are my absolute favourite new feature of the past several years as its soooo good to make my own classes now rather than having to deal with gross endless dictionaries or JObjects and the coded workflows work super nice for cross platform high code stuff, I’ve been using them more and more for my test cases also.

3 Likes

@andrzej.kniola We’ll take a look and come back via the support ticket in that case. Thanks!

@Jon_Smith Glad you enjoy it - internally we’ve built even a good couple of coded workflows only projects as well, particularly for testing.

Yes, for data objects you will always need an empty constructor, else we can’t deserialize your workflow. I guess this is something we should add an analyzer for as this is non-obvious.

We actually have a workaround for that with a PS script that goes through xaml’s and fixes assembly references. The project in question though does not use templated .cs files.

Checked. Some of the empty constructors were private, changed to public (don’t like it, but ehh), still the same issue.
Good to know though.

So going with the project in question, project validation has no errors, project analyzer has no errors, the project runs fine if run from Studio, but attempting to Publish OR right-click on some of the workflows (those that use custom types) results in error.

Here’s the error message details:

24.10.9+Branch.support-v24.10.Sha.0885b2df244a34cb4f93ed1585a57d8c8cb34b17.0885b2df244a34cb4f93ed1585a57d8c8cb34b17

One or more errors occurred. (Could not load file or assembly '[PROJECT_NAME].Core, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. Operation is not supported. (0x80131515))

Error: System.AggregateException: One or more errors occurred. (Could not load file or assembly '[PROJECT_NAME].Core, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. Operation is not supported. (0x80131515))
 ---> RemoteException wrapping System.IO.FileLoadException: Could not load file or assembly '[PROJECT_NAME].Core, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. Operation is not supported. (0x80131515)  ---> RemoteException wrapping System.NotSupportedException: Resolving to a collectible assembly is not supported. 

	--- End of inner exception stack trace ---
   at System.Reflection.RuntimeAssembly.<InternalLoad>g____PInvoke|49_0(NativeAssemblyNameParts* __pAssemblyNameParts_native, ObjectHandleOnStack __requestingAssembly_native, StackCrawlMarkHandle __stackMark_native, Int32 __throwOnFileNotFound_native, ObjectHandleOnStack __assemblyLoadContext_native, ObjectHandleOnStack __retAssembly_native)
   at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, StackCrawlMark& stackMark, AssemblyLoadContext assemblyLoadContext, RuntimeAssembly requestingAssembly, Boolean throwOnFileNotFound)
   at System.Reflection.TypeNameParser.GetType(String typeName, ReadOnlySpan`1 nestedTypeNames, String assemblyNameIfAny)
   at System.Reflection.TypeNameParser.NamespaceTypeName.ResolveType(TypeNameParser& parser, String containingAssemblyIfAny)
   at System.Reflection.TypeNameParser.GenericTypeName.ResolveType(TypeNameParser& parser, String containingAssemblyIfAny)
   at System.Type.GetType(String typeName, Boolean throwOnError)
   at UiPath.Studio.Plugin.Workflow.Triggers.TriggerEnumerationService.<>c__DisplayClass11_0.<GetWorkflowTriggersUsingDatabase>b__1(IActivityModel n)
   at UiPath.Shared.Utilities.TreeHelper.Traverse[T](T startingItem, Func`2 getChildren, Predicate`1 matcher)+MoveNext()
   at System.Linq.Enumerable.<Any>g__WithEnumerator|36_0[TSource](IEnumerable`1 source)
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
   at UiPath.Studio.Plugin.Workflow.Triggers.TriggerEnumerationService.HasTriggers(String workflowFilePath, TriggerKind triggerKind)
   at UiPath.Studio.Plugin.Workflow.Triggers.TriggerService.CanBeSetAsMain(String mainWorkflowFilePath, String workflowFilePath)
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_3.<<-ctor>g__InvokeMethod|6>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_1.<<-ctor>g__HandleRequest|3>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Server.<>c__DisplayClass7_2.<<-ctor>b__5>d.MoveNext()
--- End of stack trace from previous location ---
   at UiPath.CoreIpc.Helpers.Timeout[TResult](TimeSpan timeout, List`1 cancellationTokens, Func`2 func, String message, Func`2 exceptionHandler)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at UiPath.Studio.Plugin.Workflow.Shell.Services.DevelopmentProjectItemUiService.SetAsEntryPointControlDescription(IProjectItem item)
   at UiPath.Studio.Plugin.Workflow.Shell.Services.DevelopmentProjectItemUiService.EnumerateActions(IProjectItem projectItem)+MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at UiPath.Studio.App.Desktop.ContextMenu.ContextMenuManager.AddMenuActions(IEnumerable`1 actions, Boolean addSeparator)
   at UiPath.Studio.Shell.ViewModels.ProjectExplorerViewModel.AddSingleSelectActions(TreeNodeViewModel`1 item)
   at UiPath.Studio.App.Desktop.Trees.GenericTreeViewModel`1.ContextMenuOpening(IEnumerable`1 selectedItems, String& selectedItemName)
   at UiPath.Studio.App.Desktop.Controls.GenericTreeView.ContextMenu_ContextMenuOpening(Object sender, ContextMenuEventArgs e)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.ContentElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.Controls.PopupControlService.RaiseContextMenuOpeningEvent(IInputElement source, Double x, Double y, Boolean userInitiated)
   at System.Windows.Controls.PopupControlService.ProcessMouseUp(Object sender, MouseButtonEventArgs e)
   at System.Windows.Controls.PopupControlService.OnPostProcessInput(Object sender, ProcessInputEventArgs e)
   at System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(Tuple`2 postProcessInput, ProcessInputEventArgs processInputEventArgs)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler), HResult -2146233088

Which seems to derive from this .net change somewhere:

This looks like a rabbit hole I’m not sure if I’d like to go through, at least right now, or if from a user perspective if this is something that even can be affected.

Coded source files are pretty easy to get working correctly, when avoiding the common pitfalls. And I do agree that they are a game changer.
What we did before was write quite a bit of classes that would expose functionality that would fit more into coded workflows, which were not ready at that time for real production use (in our opinion).
Now with 24.10 we would really want to move into doing things “properly”, so we’re moving away from function-classes into coded workflows. And things fall apart, unfortunately.
The most irritating part is that the code in the .cs files itself is completely fine. It compiles, it runs. And yet somewhere along the internal studio processes something breaks, and it’s a blind hunt on what it could be.

And I totally agree with you on the usability - being able to write C# directly within the Studio is a complete game changer, and (if it wouldn’t break for us so often…) a real multiplier in what can be done and how fast. That’s the thing that’s enraging me the most. It should work, I want it to work, the code itself works, but the totality of it doesn’t.
So as a broader group, it’s not even about if I can make my project work after it breaks in the compilation phases. It’s about how “easy” (or at least seemingly so) it is to break it and not realize until you’re 20 commits in and trying to publish. Peeling that onion back is painful, and costly.
Hopefully the root cause(s) will be found and fixed. I can fully believe it’s something that we’re doing that is breaking it. But even after 10y of doing UiPath, and more in .Net, I can’t find what is actually breaking, so our production support team is not even gonna step near this, and rightfully so.

1 Like

Just to update the topic - the error posted in the previous post is confirmed as a bug and a fix should come very soon (as it blocks publishing and part of the project configuration).

1 Like

Short update:
We’re testing the issue with 24.10.11 released yesterday → so far it looks promising, will update after more extensive tests.
EDIT: 2025-04-22 → the update seems to have fixed the main issue. So all that’s left is below:

In the meantime, the general question still holds → would be nice to have a “don’t do this in coded workflows/source files” list somewhere in docs (and if it’s there, I couldn’t find it)

1 Like

Glad to hear that the main issue was solved. Regarding having a do’s / don’ts list, we’d ideally capture that in our code analyzers, however for 24.10.x we should definitely clearly document that objects used as arguments in workflows must have an empty constructor (in order for the serialization/deserialization to work), as it’s very important, and caveats around renaming templates and their namespaces.

Thanks,
Alvin

1 Like

Perhaps have the constructor there as default when you make the Class Alvin?

Feels like a simply thing to add that means people actively have the delete the empty constructor when making a coded Source File.

You could include a comment there aswell indicating to not delete it.

The Coded workflows already have this kind of templating and ‘helper’ comments, Coded Source files could benefit from the same.

3 Likes

Great idea, @Jon_Smith, thanks, we’ll add that!

1 Like

My experience is that whenever you work with Coded Workflows, or Coded Source Files, you should keep everything absolutely vanilla and basic, and pay attention to the output console of your UiPath Studio often. Whenever you write some code, after that just check the output window, and the “Updated coded types available to workflows based on the latest changes” message should appear if the compiler or preprocessor is all fine with everything. That is because Studio preprocessor and compiler can behave in very weird ways.
For example once I realised that #region directive is fine around properties or variable definition, if condition code blocks, BUT when i want to encapsulate a c# function definition in a #region that will cause UiPath off and it will throw error.

1 Like