Not quite Friday, but an Idea born out of Frustration, Better Exception Traceability

KIN-I-5531 - Bubble Up Culprit BPM / Function / Method Directive / Data Directive in Exception

I just spent the better part of 2 hours trying to find a bad data directive, the Only information I had was this exception in system agent.

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> Ice.Common.RecordNotFoundException: Record not found.
   at Epicor.Customization.Bpm.DirectiveBase`2.ProcessRememberedExceptions() in C:\_releases\ICE\ICE4.2.300.9\Source\Server\Internal\Lib\Epicor.Customization.Bpm\DirectiveBase.Generic.cs:line 293
   at Epicor.Customization.Bpm.DirectiveBase`2.Execute(TParam parameters) in C:\_releases\ICE\ICE4.2.300.9\Source\Server\Internal\Lib\Epicor.Customization.Bpm\DirectiveBase.Generic.cs:line 222
   at Epicor.Customization.Bpm.TriggerBase`2.RunDirectives(TriggerParameters`1 parameters) in C:\_releases\ICE\ICE4.2.300.9\Source\Server\Internal\Lib\Epicor.Customization.Bpm\TriggerBase.cs:line 51
   at Epicor.Customization.Bpm.CustomizationBase2`2.Execute(TParam parameters) in C:\_releases\ICE\ICE4.2.300.9\Source\Server\Internal\Lib\Epicor.Customization.Bpm\CustomizationBase2.cs:line 98
   at Epicor.Customization.Bpm.InTranTriggerBase2`2.Delete(LinqRow oldRecord) in C:\_releases\ICE\ICE4.2.300.9\Source\Server\Internal\Lib\Epicor.Customization.Bpm\InTranTriggerBase2.cs:line 73
   at Ice.Triggers.TriggerQueue.ExecuteBpmDeleteTrigger(IceDataContext context, LinqRow originalRecord) in C:\_releases\ICE\ICE4.2.300.9\Source\Server\Framework\Epicor.System\Triggers\TriggerQueue.cs:line 363
   at Ice.Triggers.TriggerQueue.RunDeleteTrigger(IceDataContext context, LinqRow linqRow) in C:\_releases\ICE\ICE4.2.300.9\Source\Server\Framework\Epicor.System\Triggers\TriggerQueue.cs:line 131
   at Ice.IceDataContext.DeleteObject(Object entity) in C:\_releases\ICE\ICE4.2.300.9\Source\Server\Framework\Epicor.System\Data\IceDataContext.cs:line 223
   at Erp.Internal.PE.Bank_ReconciliationPost_Post.UpdateRelatedTables(String ABTUID) in C:\_releases\ERP\ERP11.2.300.0\Source\Server\Internal\PE\Bank_Reconciliation\Bank_ReconciliationPost_Post.cs:line 246
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
   at Erp.Internal.PE.ReviewJournal.__ConfirmRJ(Int32 iRvJrnUID, Int32 iACTTypeUID, String iABTUID, Boolean lBankRecFakeUpdate) in C:\_releases\ERP\ERP11.2.300.0\Source\Server\Internal\PE\ReviewJournal\ReviewJournal.cs:line 3244

Now from looking at the stack trace i can clearly see the issue came from a BPM, Specifically an InTranTrigger (Data Directive) but nowhere in that stack is information about which table, method, BO or source.

It required me to hook up a .NET Debugger so I could step through the exception to then find out that it came from a poorly written GetByID in ApChkGrp Data Directive which assumed you’d always have a valid PMUID.

The issue at hand here is that the stack trace provided by .NET doesn’t tell us where to look and it can be incredibly time consuming to troubleshoot. If we pass the name and or locatoin (Table, BO, Method) of the Directive into DirectiveBase and then use standard Try Catch Throw you can append to the stack / message the location of said bad directive and save me hours… and hair on my head~

Confused Always Sunny GIF by It's Always Sunny in Philadelphia

6 Likes

Not to poo your idea, it’s great, and I want it built in, but I have been doing that manually in mine.

I catch errors, add context, and rethrow if I want it to throw.

Would sure be nice if it was built in though.

2 Likes

Why bubble-up errors if you can log them where they fail?

Kinetic self service Usage Telemetry | Epicor Ideas (2840)

Monitoring is one of the segments of DevOps…

Guess Big Sky GIF by ABC Network

4 Likes

Happy Joel Mchale GIF by ABC Network

4 Likes

In a Dev environment, sure! In production? :thinking:

1 Like

I have situations where I want it to fail even in production.
Helpful error messages are nice. A necessity, no. I use my logging for that.

4 Likes

Yes, I think we are in agreement. Letting the user know something unexpectedly happened? Absolutely. Telling them the .NET DLL name and a mini-dump with sensitive information? Not so much.

3 Likes

Right but I have 200+ existing BPMs, you wanna go add that stuff in for me in Hindsight? :joy:

3 Likes

I mean this error happened in production. Exceptions happen in production all the time. Errors (useful ones) should bubble up (even if in a log)

At the moment the log just says Epicor :poop: the bed, get bent! Which is not useful. What I’m asking for is the ability to dig through said logs and find out what the heck happened. Particularly in a HALT operation as this one. Mid transaction crap blew up

4 Likes

Dax Shepard Money GIF

or we could horse trade some advanced coding training…

2 Likes

This is the idea I posted above. Nothing to add to your code.

3 Likes

I implemented that as a test myself. Then “Big Epicor” shut me down. :rofl:

That would be better implemented on the backend properly though.

4 Likes

@timshuwy is the one who added the idea to put that back in. :person_shrugging:

3 Likes

I need this as a custom error message in Epicor!

7 Likes

Now you got me curious, what was the problem?

1 Like

The Directive assumed that you would always had a valid Payment Method and so it didn’t check if it had a result it just tried to use it which lead to an Array out of Index error.

4 Likes

I wonder how many of those situations exist in every Epicor environment…

2 Likes

Well they did add that flag in Company maint if the environment is Prod or not, and you can have a condition to check for that.
But a debug mode would be nice… wait… isn’t there a debug checkbox already there.

While not this exactly, just yesterday I tripped across something where it appears a BPM isn’t working at all, but it’s not marked as Out of Date and it doesn’t throw any obvious errors. It just silently doesn’t do the thing… for months and no one reported it!.. which @Mark_Wonsil can rightly point out that the BPM wasn’t designed to catch/log when it doesn’t do what it’s expected to do.
But to @josecgomez point, the error messages are terrible as they don’t really provide any USEFUL context.
BPM’s seem to be designed for the ‘non programmer’ but then to expect ‘non programmers’ to include complex error handling/logging seems a bit too much of an ask, if only when an error does occur it can provide useful context.
I try to battle this by including the Directive BO, Method, type and name in any messages or emails that are generated.

5 Likes

You know I feel that I am seeing more and more of this sort of situation. Recently came across checking syntax on GL Transaction types, no error, but then making it active I see an error in the event logs…

1 Like