Epicor Function with CallService: TransactionAbortedException: The transaction has aborted

I have a simple Epicor Function for creating a new record. A user had an error that I traced back to this function. Instead of the function catching the error and returning it, it escaped and they got an unhandled exception “We aplogize..”

The error I found in the server log was System.Transactions.TransactionAbortedException: The transaction has aborted.

try
{
  this.CallService<Ice.Contracts.UD14SvcContract>(UD14svc =>
  {
    var ds = new UD14Tableset();
    var UI =  Guid.NewGuid().ToString();
    UD14svc.GetaNewUD14(ref ds);
    ds.UD14[0].Key1 = this.Quote;
    ds.UD14[0].Key2 = this.QuoteLine;
    ds.UD14[0].Key3 = this.Configuration ;
    UD14svc.Update(ref ds);
    var ds2 = UD14svc.GetByID(this.Quote,this.QuoteLine,this.Configuration,"","");
    this.returnObj = ds2;
    this.error = "No error";
    
  });
}
catch (Exception e)
{
  error = e.ToString();
}


This user is super click happy so I was wondering if somehow they hit the button twice and there was two new records in scope with the same keys both trying to be committed? Seems super unlikely but I can’t see what could go wrong here.

2 Likes

The multiple transactions isn’t a bad theory. Is it possible the error is hitting AFTER the try/catch when it tries to return the object ds2?

1 Like

You mean when the function is returning? I would think the transaction scope would have been closed by then. The line this.returnObj = ds2; should be inside the try/catch block I would think

2 Likes

Also, are you multi-company? I though Company was one of the parameters in UDXXSvc.GetByID

1 Like

Right, I don’t think it’s getting the error when you set the value. But it then returns the value. But it will then exit the Try/Catch, and return the response parameter outside the Try/Catch, but still within the Transaction Scope

1 Like

We are not multi company, I can make Key1 whatever I want:

2 Likes

Is this.returnObj type = Ice.Tablesets.UD14Tableset?

1 Like

Yes

1 Like

You might be able to get a more useful error message if you check inner exceptions, and also output the exception type, it may be a specific type of exception that contains more detail on either the outer or inner. unfortunately that would require duplicating, though.

1 Like

How can I even do that when its escaping my try/catch? :thinking:

1 Like

Put another Try/Catch block inside this block, it should catch it then.

1 Like

Ok, I did that. Now I wait I guess

1 Like

Try an exception block like this too, it will walk through inner exceptions, and also output the exception type.
If it is a specifically typed Exception, you can handle it appropriately for more info.

} catch (Exception ex) {
    var exinfo = "";
    for (var cur = ex; cur != null; cur = cur.InnerException)
        exinfo += $"[Level {level++}] Type: {cur.GetType().Name} | Msg: {cur.Message} | Stack: {cur.StackTrace}\n";
    log($"Exception: {exinfo}");
}
} catch (Epicor.Customization.CompilationException ex) {
    string xi = "";
    foreach (var msg in ex.ExceptionMessageList) {
      foreach (var str in msg.Errors) {
        xi += $"Error: {str}\r\n ";
      }
    } 
    log(xi);
}
2 Likes