How do we even Function?

Kevin’s post got me thinking.

But first, a little background. Last year, RFC9457 - Problem Details for HTTP APIs started to get a lot of love:

The basic idea is to have a standard (yet extensible) error response for APIs. Give something useful to the client when there are issues.

At @Olga’s session on Kinetic Functions at Insights 2025, there was a question from the audience from Nathaniel Dickerson (Melton Machine and Control). He wanted to know, how does the UI know there was an error in an http request within the function? Good question, since the function will probably still return a 200 OK (unless the function is demoted, then it returns a 404). What should happen at the UI?

Maybe the Problem Details spec can help us out here. What does it look like? At a minimum it includes these fields:

{
 "type": "https://example.net/validation-error",
 "title": "Your request is not valid.",
 "status": "400"
}

Type is a URI that points to a location for further explanation. Don’t have one yet? about:blank works just fine. The title is a general summary of the error. Status is the HTTP status code. There is more as you will see at the RFC or in the videos, but this is a minimum.

What if we, function authors, “standardized” one of our return objects to include a “Problem Details” object? :thinking: If we did, we could pass information back to the client when something within our function goes astray. I can imagine logic in our Kinetic Applications querying the result object and displaying useful information back to the user or even take some action on behalf of the user to remediate the problem.

Thoughts?

3 Likes

I did play around a little to create a function that formats an error object and optionally logs it with Ice.Diagnostics.Log.WriteEntry.

// Create RFC 9457 Object and write to log. - https://www.rfc-editor.org/rfc/rfc9457

var ProblemDetails = new System.Text.Json.Nodes.JsonObject
{
  ["type"] = iType,
  ["title"] = iTitle
};

// Add Optional nodes
if (!string.IsNullOrEmpty(iStatus))
{
  ProblemDetails.Add("status", iStatus);
}
else // If no status passed, assume good.
{
  ProblemDetails.Add("status", "200");
}
if (!string.IsNullOrEmpty(iDetails))
{
  ProblemDetails.Add("detail", iDetails);
}  
if (!string.IsNullOrEmpty(iInstance))
{
  ProblemDetails.Add("instance", iInstance);
}  

// Add Json nodes for Extended Details
if (!string.IsNullOrEmpty(iExtendedDetails))
{
  System.Text.Json.Nodes.JsonObject extDetails = (System.Text.Json.Nodes.JsonNode.Parse(iExtendedDetails)).AsObject();
  foreach (var kvp in extDetails)
  {
    ProblemDetails.Add(kvp.Key, kvp.Value);  
  }
}

if (iLogLevel > 0)
{
  Ice.Diagnostics.Log.WriteEntry(ProblemDetails.ToString());
}
4 Likes

This is what happens:

Response

{
    "HttpStatus": 400,
    "ReasonPhrase": "REST API Exception",
    "ErrorMessage": "poop",
    "ErrorType": "Ice.BLException",
    "ErrorDetails": [
        {
            "Message": "poop",
            "Type": "Error",
            "Program": "efx.pawelpdfdemo.dll",
            "Method": "Run"
        }
    ],
    "CorrelationId": "65ea1fcf-2d28-4563-b7d0-2c37c6acf309"
}

Note, that’s if you catch it and throw a BLException.

If it just errors, or you throw something else, you will get a 500 and..

We apologize, but an unexpected internal problem occurred. Please provide your System Admin or Technical Support this Correlation ID for further details. Correlation ID: 3059819d-9078-4c99-863d-c9c1cbf4684e

Our “Standard” at Stephen Gould for ALL functions is to have at least 3 output parameters (You can have more) but we require all functions to return

Success: boolean
ErrorMessage: string
InfoMesssage:string

Success true means whatever the function needed to do got done
If it encounters errors the response is Success: false, and User Displayable message goes in the ErrorMessage param

InfoMessage is / can also be displayed to the user on Succes: true

2 Likes

Nice. We do more or less the same thing.

Are these helpful messages for the user? Would @aosemwengie1 like it?

Should everyone follow the SG standard, the Mid South Standard, or the Rose Brand standard when we’re in Kinetic and an RFC when we make APIs in ASP.NET, where Problem Details is a built-in capability?

Do we think that RFC 9457 is not worth the squeeze? Maybe I’m just drinking the Kool-Aid, but It does seem to provide a more useful message to the user.

You know me. I’m always looking for ways to avoid making pets… :person_shrugging:

3 Likes

I have been slowly converting to something similar.

Coming from the EDI world, the nice part about standards is that everybody has one!

:rofl:

4 Likes

Absolutely, but out of all the ideas that Epicor should be working on, I rather they spend their time in other areas this can be easily solved with a company standard.

But I do like it

1 Like

Oh, for sure. But if the users adopted the concept organically, it would be an easier lift in the future, no?

2 Likes

Like a wiki?
Think Stephen Colbert GIF by The Late Show With Stephen Colbert

3 Likes

I was thinkinig more like 4:20
Smoke Weed GIF

1 Like

at least she knew to pass it left.

4 Likes

You speak the truth. The only things “standard” are the version, document, segment and element conventions. Actual usage of them is absolutely positively 100% random on a partner by partner basis and 100% subject to change without notice.

1 Like

Maybe I’m doing something wrong. Clicking on search should call the function:

But I don’t get a dialog for error even though I have a 404. :thinking:

That on success thing seems to fire even when it fails. I usually direct on success to a condition, and then check for an error there.

2 Likes