Skip to main content
Question

26R1 upgrade: long running process error on SO301000 page (RESTAPI)

  • September 23, 2026
  • 8 replies
  • 41 views

Forum|alt.badge.img+2

Since upgrading from 24R1 to 26R1, I’ve been getting the following errors from the RESTAPI using the SO301000 screen:

{"message":"A long operation is running for this screen in the current session. Please try again later."}

 

This didn’t happen at all in 24R1 and the small number long running processes that I’ve found on the System Monitor screen only run for a couple of seconds at the most.  Is there a way to prevent this error from occurring since I have no control over which schedules use PXLongOperation.StartOperation()?

8 replies

JKurtz29
Varsity II
Forum|alt.badge.img+1
  • Varsity II
  • September 23, 2026

You might have just been getting lucky in the past. 

When you submit your call, you should get a response with a “Location” URL that you can test to see if the process is still running.  Here is a link in the Help that talks about this process (Status code 202):

https://help.acumatica.com/Help?ScreenId=ShowWiki&pageid=91bf9106-062a-47a8-be1f-b48517a54324


Forum|alt.badge.img+2
  • Author
  • Semi-Pro III
  • September 23, 2026

You might have just been getting lucky in the past. 

When you submit your call, you should get a response with a “Location” URL that you can test to see if the process is still running.  Here is a link in the Help that talks about this process (Status code 202):

https://help.acumatica.com/Help?ScreenId=ShowWiki&pageid=91bf9106-062a-47a8-be1f-b48517a54324

No, it’s definitely not luck since the same RESTAPI is used constantly throughout the day (every 5 minutes) and this RESTAPI error didn’t come up until right after the upgrade.  The only response I get is the JSON that I’ve provided...no Location URL.


Steve Milner
Varsity III
Forum|alt.badge.img+4
  • Varsity III
  • September 23, 2026

@bpgraves, your schedules aren't what's tripping this. In 26R1 the API checks for a running operation on SO301000 in the same session that sent the call. The key for that check comes from your integration's own login session. An operation started under any other session, scheduled ones included, can't set it off. Something your integration started on Sales Orders was still running when the next call came in.

That's also why you don't see a Location URL. Jerry has the right pattern. The URL comes back on the call that started the operation, not on the one that gets rejected. An action call (POST to /SalesOrder/<action name>) can answer 202 and keep running in the background. A PUT or DELETE waits for anything its own save kicks off before it responds, so those don't leave work behind. Log the status code on every call and look for a 202 just before each failure.

Once you find it:
- The same job sends the next call: poll that Location URL until it returns 204, then carry on.
- A different job shares the session: give each job its own sign-in and sign-out so one can't block the other.

A rejected PUT never gets as far as the save, so waiting a few seconds and resending is a safe backstop.


Forum|alt.badge.img+2
  • Author
  • Semi-Pro III
  • September 23, 2026

@bpgraves, your schedules aren't what's tripping this. In 26R1 the API checks for a running operation on SO301000 in the same session that sent the call. The key for that check comes from your integration's own login session. An operation started under any other session, scheduled ones included, can't set it off. Something your integration started on Sales Orders was still running when the next call came in.

That's also why you don't see a Location URL. Jerry has the right pattern. The URL comes back on the call that started the operation, not on the one that gets rejected. An action call (POST to /SalesOrder/<action name>) can answer 202 and keep running in the background. A PUT or DELETE waits for anything its own save kicks off before it responds, so those don't leave work behind. Log the status code on every call and look for a 202 just before each failure.

Once you find it:
- The same job sends the next call: poll that Location URL until it returns 204, then carry on.
- A different job shares the session: give each job its own sign-in and sign-out so one can't block the other.

A rejected PUT never gets as far as the save, so waiting a few seconds and resending is a safe backstop.

Are you referring to the URL that is making the call to RESTAPI?  I am logging my Request/Response only since the URL is created by me when I call the RESTAPI.  Like I said, the only response is the message I noted above.  I’m really not sure where the Location URL come in since I’ve never seen that when I get the long running process error. 

However, from what you’re saying, one of RESTAPI calls is the long running process that is still open when the next RESTAPI call is made.  Perhaps I need to submit each RESTAPI call with a timeout/cancellation?  I’m not sure is that’s the issue...currently I’m not setting one.


Steve Milner
Varsity III
Forum|alt.badge.img+4
  • Varsity III
  • September 23, 2026

@bpgraves, no, not your request URL. Location is a response header, not part of the body. Acumatica sends it with a 202 status, and only on the call that started the operation. The call that fails afterward never carries it. If your log only captures the response body, you won't see it even when it's there.

A timeout won't help. Cancelling on your side doesn't stop anything on the server. The operation runs on its own thread and finishes whether your client is still waiting or not. A timeout just sends your next call out sooner, into the same error.

Log the HTTP status code and the response headers on every call for a day. When the error shows up, look at the call just before it in the same session. If that one came back 202, that's your culprit. Take the Location URL from its headers and GET it until it returns 204, then send the next call.

If nothing in the run ever comes back 202, post the sequence of calls your job sends and I'll take another look.


Forum|alt.badge.img+2
  • Author
  • Semi-Pro III
  • September 23, 2026

@bpgraves, no, not your request URL. Location is a response header, not part of the body. Acumatica sends it with a 202 status, and only on the call that started the operation. The call that fails afterward never carries it. If your log only captures the response body, you won't see it even when it's there.

A timeout won't help. Cancelling on your side doesn't stop anything on the server. The operation runs on its own thread and finishes whether your client is still waiting or not. A timeout just sends your next call out sooner, into the same error.

Log the HTTP status code and the response headers on every call for a day. When the error shows up, look at the call just before it in the same session. If that one came back 202, that's your culprit. Take the Location URL from its headers and GET it until it returns 204, then send the next call.

If nothing in the run ever comes back 202, post the sequence of calls your job sends and I'll take another look.

I need to totally rewrite how I submit a sales order through the RESTAPI just to log these things that's you’re asking for.  Before I do this, I need some clarification.

Are you talking about RedirectLocation in the HttpResponse (C#)?  I’m still not understanding what Location you’re referring to. Is Location from the HttpResponseHeaders?

https://learn.microsoft.com/en-us/dotnet/api/system.net.http.headers.httpresponseheaders?view=net-10.0

I’m assuming the status code is here (please let me know if I’m wrong):

https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpresponsemessage?view=net-10.0

 

Also, what kind of polling are you referring to?  Are there any C# examples I can look at somewhere?


Steve Milner
Varsity III
Forum|alt.badge.img+4
  • Varsity III
  • September 23, 2026

@bpgraves, yes, HttpResponseHeaders. With HttpClient it's all on the HttpResponseMessage you already read the body from: response.StatusCode and response.Headers.Location (a Uri). RedirectLocation is the server-side ASP.NET property, so not that one. You shouldn't need a rewrite, just two more values where you log the response.

Check one thing before you change anything. On Sales Orders only an action call (a POST to /SalesOrder/<action name>) comes back 202. PUTs don't. If your code never POSTs to an action, there's no 202 to find and the cause is somewhere else.

Polling means a GET to that Location URL on the same HttpClient, so it stays in the same session, until it stops answering 202. 204 means the operation finished. Roughly:

var resp = await client.PostAsync(actionUrl, body);
if (resp.StatusCode == HttpStatusCode.Accepted)
{
    var statusUrl = new Uri(resp.RequestMessage.RequestUri, resp.Headers.Location);
    while ((await client.GetAsync(statusUrl)).StatusCode == HttpStatusCode.Accepted)
        await Task.Delay(1000);
}

Acumatica's own C# client works the same way. InvokeAction returns the Location header and WaitActionCompletion polls it every second until 204. Their console example wraps every action call in it:
https://github.com/Acumatica/AcumaticaRESTAPIClientForCSharp/blob/6.0/Acumatica%20REST%20API%20Console%20Application/RESTExample.cs#L155-L163


Forum|alt.badge.img+2
  • Author
  • Semi-Pro III
  • September 23, 2026

@bpgraves, yes, HttpResponseHeaders. With HttpClient it's all on the HttpResponseMessage you already read the body from: response.StatusCode and response.Headers.Location (a Uri). RedirectLocation is the server-side ASP.NET property, so not that one. You shouldn't need a rewrite, just two more values where you log the response.

Check one thing before you change anything. On Sales Orders only an action call (a POST to /SalesOrder/<action name>) comes back 202. PUTs don't. If your code never POSTs to an action, there's no 202 to find and the cause is somewhere else.

Polling means a GET to that Location URL on the same HttpClient, so it stays in the same session, until it stops answering 202. 204 means the operation finished. Roughly:

var resp = await client.PostAsync(actionUrl, body);
if (resp.StatusCode == HttpStatusCode.Accepted)
{
    var statusUrl = new Uri(resp.RequestMessage.RequestUri, resp.Headers.Location);
    while ((await client.GetAsync(statusUrl)).StatusCode == HttpStatusCode.Accepted)
        await Task.Delay(1000);
}

Acumatica's own C# client works the same way. InvokeAction returns the Location header and WaitActionCompletion polls it every second until 204. Their console example wraps every action call in it:
https://github.com/Acumatica/AcumaticaRESTAPIClientForCSharp/blob/6.0/Acumatica%20REST%20API%20Console%20Application/RESTExample.cs#L155-L163

I’ve always done a PUT (not a POST) to create the Sales Order.  So you’re saying that my status code will never be 202?