Skip to main content
Answer

Another Process Has Updated 'SOAddress' Record, after updating SOAddress in FieldUpdated

  • November 5, 2025
  • 11 replies
  • 105 views

Forum|alt.badge.img+8

Hello everyone,

 

I have a FieldUpdated handler for SOOrder.ShipVia which works fine, but upon saving, Acumatica throws the error ‘Another process has updated the ‘SOAddress’ record.

 

if (e.Row.ShipVia == "W" && oldValue != "W")
{
INSite site = INSite.PK.Find(Base, order.DefaultSiteID);
if (site != null)
{
Address siteAddr = Address.PK.Find(Base, site.AddressID);
if (siteAddr != null)
{
SOShippingAddress address = Base.Shipping_Address.Current = Base.Shipping_Address.Select();
if (address != null)
{
address.OverrideAddress = true;
Base.Shipping_Address.Update(address);
address = Base.Shipping_Address.Current;
address.AddressLine1 = siteAddr.AddressLine1;
address.AddressLine2 = siteAddr.AddressLine2;
address.City = siteAddr.City;
address.CountryID = siteAddr.CountryID;
address.State = siteAddr.State;
address.PostalCode = siteAddr.PostalCode;
Base.Shipping_Address.Update(address);
Base.Shipping_Address.Cache.IsDirty = true;
}
}
else
{
throw new PXSetPropertyException(Helper.Messages.ShippingAddressForWalkIn, PXErrorLevel.Error);
}
}

Debugging takes me to the end of the file. 

This is the trace:

   at PX.Data.PXFirstChanceExceptionLogger.ProfilerFirstChanceException(Object o, FirstChanceExceptionEventArgs args)
   at PX.Data.PXCache`1.PersistUpdated(Object row, Boolean bypassInterceptor)
   at PX.Objects.CS.SharedRecordAttribute.RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
   at PX.Objects.SO.SOAddressAttribute.RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
   at PX.Data.PXCache.AttributeHandlersSquasher`1.<>c__DisplayClass2_0`1.<To>b__0(PXCache cache, TArgs args)
   at PX.Data.PXCache.OnRowPersisting(Object item, PXDBOperation operation)
   at PX.Data.PXCache`1.PersistUpdated(Object row, Boolean bypassInterceptor)
   at PX.Data.PXCache`1.Persist(PXDBOperation operation)
   at PX.Data.PXGraph.Persister.Persist(Type cacheType, PXDBOperation operation)
   at PX.Data.PXGraph.PerformPersist(IPersistPerformer persister)
   at PX.Data.PXGraph.TransactionalPersist()
   at PX.Data.PXGraph.RetryTransaction(Action persistBody, Int32 maxRetries)
   at PX.Data.PXGraph.Persist()
   at PX.Objects.SO.SOOrderEntry.PersistImpl()
   at PX.Objects.SO.SOOrderEntry.Persist()
   at PX.Objects.CC.GraphExtensions.SOOrderEntryPayLink.Persist(Action baseMethod)
   at PX.Objects.Extensions.ProcessAffectedEntitiesInPrimaryGraphBase`4.Persist(Action basePersist)
   at PX.Objects.Extensions.ProcessAffectedEntitiesInPrimaryGraphBase`4.Persist(Action basePersist)
   at PX.Objects.Extensions.ProcessAffectedEntitiesInPrimaryGraphBase`4.Persist(Action basePersist)
   at PX.Objects.SO.GraphExtensions.SOOrderEntryExt.CreatePaymentAPIExt.Persist(PersistDelegate baseMethod)
   at PX.Objects.Common.GraphExtensions.Abstract.TransactionZeroBaseQtyValidationExtension`3.Persist(Action basePersist)
   at PX.Data.PXSave`1.<HandlerInternal>g__Persist|3_2()
   at PX.Data.PXSave`1.<HandlerInternal>d__3.MoveNext()
   at PX.Data.PXAction`1.<Press>d__39.MoveNext()
   at PX.Web.UI.PXBaseDataSource.tryExecutePendingCommand(String viewName, String[] sortcolumns, Boolean[] descendings, Object[] searches, Object[] parameters, PXFilterRow[] filters, DataSourceSelectArguments arguments, Boolean& closeWindowRequired, Int32& adapterStartRow, Int32& adapterTotalRows)
   at PX.Web.UI.PXBaseDataSource.ExecuteSelect(String viewName, DataSourceSelectArguments arguments, PXDSSelectArguments pxarguments)
   at PX.Web.UI.PXDataSource.ExecuteSelect(String viewName, DataSourceSelectArguments arguments, PXDSSelectArguments pxarguments)
   at PX.Web.UI.PXDataSourceView.Select(DataSourceSelectArguments arguments, PXDSSelectArguments swarguments, DataSourceViewSelectCallback callback)
   at PX.Web.UI.PXFormDataProvider.DataBind()
   at PX.Web.UI.PXCallbackManager.CollectDataControls(Dictionary`2 controlsDic, List`1 controlsList)
   at PX.Web.UI.PXCallbackManager.RenderClientData(PXCallbackResultMethod resultMethod, XmlWriter writer)
   at PX.Web.UI.PXCallbackManager.GetCallbackResultInternal(PXCallbackResultMethod resultMethod)
   at PX.Web.UI.PXCallbackManager.GetCallbackResult(PXCallbackResultMethod resultMethod)
   at System.Web.UI.Page.RenderCallback()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at PX.Web.UI.PXPage.ProcessRequest(HttpContext context)
   at ASP.cstpublished_pages_so_so301000_aspx.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.<>c__DisplayClass285_0.<ExecuteStepImpl>b__0()
   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
   at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
   at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
   at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
   at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
 

 

Has anyone experienced anything similar before?

Best answer by Django

I use the following code:

{
SOShippingAddress address = new SOShippingAddress();
address.OverrideAddress = true;
address.CustomerID = soGraph.Document.Current.CustomerID;
address.CustomerAddressID = cust.DefBillAddressID;
address.AddressLine1 = rec.ShippingAddrStreetString;
address.City = rec.ShippingAddrCity;
address.State = rec.ShippingAddrRegionCode;
address.PostalCode = rec.ShippingAddrPostcode;
address.CountryID = rec.ShippingAddrCountryId;
address.RevisionID = 0;
soGraph.Shipping_Address.Current = address = soGraph.Shipping_Address.Insert(address);
soGraph.Document.Current.ShipAddressID = address.AddressID;
}

 

11 replies

Forum|alt.badge.img+7
  • Captain II
  • Answer
  • November 6, 2025

I use the following code:

{
SOShippingAddress address = new SOShippingAddress();
address.OverrideAddress = true;
address.CustomerID = soGraph.Document.Current.CustomerID;
address.CustomerAddressID = cust.DefBillAddressID;
address.AddressLine1 = rec.ShippingAddrStreetString;
address.City = rec.ShippingAddrCity;
address.State = rec.ShippingAddrRegionCode;
address.PostalCode = rec.ShippingAddrPostcode;
address.CountryID = rec.ShippingAddrCountryId;
address.RevisionID = 0;
soGraph.Shipping_Address.Current = address = soGraph.Shipping_Address.Insert(address);
soGraph.Document.Current.ShipAddressID = address.AddressID;
}

 


Forum|alt.badge.img+1

Hi ​@aiwan 

The error “Another process has updated the <DAC> record” in Acumatica is rare, but when it does occur, it can be difficult to fix.

This error typically occurs due to optimistic concurrency conflicts in Acumatica. It means the SOAddress record was modified by another process after it was loaded into memory, and your update is now based on a stale version.

Root Causes in the Original Code

  • Manual reassignment of Base.Shipping_Address.Current using Select() can lead to stale data.
  • Multiple calls to Update() on the same record may cause version mismatches.
  • Unnecessary use of Select() when Current is already available.
  • Other event handlers might be modifying SOAddress concurrently.

Best Practices to Avoid the Error

  • Use Base.Shipping_Address.Current directly instead of Select() unless you need to requery.
  • Avoid multiple Update() calls — set all fields first, then update once.
  • Use PXCache.SetValueExt() for safer field updates.
  • Ensure no other handlers are modifying the same record simultaneously.

Revised Code Block (Safe Version)

if (e.Row.ShipVia == "W" && oldValue != "W")
{
INSite site = INSite.PK.Find(Base, order.DefaultSiteID);
if (site != null)
{
Address siteAddr = Address.PK.Find(Base, site.AddressID);
if (siteAddr != null)
{
SOShippingAddress address = Base.Shipping_Address.Current;
if (address != null)
{
address.OverrideAddress = true;
address.AddressLine1 = siteAddr.AddressLine1;
address.AddressLine2 = siteAddr.AddressLine2;
address.City = siteAddr.City;
address.CountryID = siteAddr.CountryID;
address.State = siteAddr.State;
address.PostalCode = siteAddr.PostalCode;

Base.Shipping_Address.Update(address);
}
}
else
{
throw new PXSetPropertyException(Helper.Messages.ShippingAddressForWalkIn, PXErrorLevel.Error);
}
}
}

 

Revised Code Block Using SetValueExt<> for Safe Updates 

if (e.Row.ShipVia == "W" && oldValue != "W")
{
INSite site = INSite.PK.Find(Base, order.DefaultSiteID);
if (site != null)
{
Address siteAddr = Address.PK.Find(Base, site.AddressID);
if (siteAddr != null)
{
SOShippingAddress address = Base.Shipping_Address.Current;
PXCache cache = Base.Shipping_Address.Cache;

if (address != null)
{
cache.SetValueExt<SOShippingAddress.overrideAddress>(address, true);
cache.SetValueExt<SOShippingAddress.addressLine1>(address, siteAddr.AddressLine1);
cache.SetValueExt<SOShippingAddress.addressLine2>(address, siteAddr.AddressLine2);
cache.SetValueExt<SOShippingAddress.city>(address, siteAddr.City);
cache.SetValueExt<SOShippingAddress.countryID>(address, siteAddr.CountryID);
cache.SetValueExt<SOShippingAddress.state>(address, siteAddr.State);
cache.SetValueExt<SOShippingAddress.postalCode>(address, siteAddr.PostalCode);

cache.Update(address);
}
}
else
{
throw new PXSetPropertyException(Helper.Messages.ShippingAddressForWalkIn, PXErrorLevel.Error);
}
}
}

I hope this will be of assistance. 


Dmitrii Naumov
Acumatica Moderator
Forum|alt.badge.img+7
  • Acumatica Moderator
  • November 6, 2025

@aiwan first of all, you should not update other cache records in FieldUpdated event. Use RowUpdated event for that purpose.

Second, setting Cache.IsDirty=true is not necessary here, and it is better to remove it from the code.

Third, I think you need to create a new address record as in the ​@Django ‘s example


darylbowman
Captain II
Forum|alt.badge.img+15

Not sure if this will be helpful, but I discovered a nifty little method in AddressAttribute:

SOAddress soAddress = SelectFrom<SOAddress>.
Where<SOAddress.addressID.IsEqual<P.AsInt>>.
View.Select(Base, soorder.ShipAddressID);

AddressAttribute.CopyRecord<POOrder.shipAddressID>(Base.Document.Cache, order, soAddress, false);

 


darylbowman
Captain II
Forum|alt.badge.img+15

​first of all, you should not update other cache records in FieldUpdated event. Use RowUpdated event for that purpose.

Could you expound on this a bit more?


Forum|alt.badge.img+8
  • Author
  • Captain II
  • November 6, 2025

​first of all, you should not update other cache records in FieldUpdated event. Use RowUpdated event for that purpose.

Could you expound on this a bit more?

@Dmitrii Naumov I second this, I’ve always used e.Cache.SetValeExt in FieldUpdated. I believe T210 details this.


Forum|alt.badge.img+8
  • Author
  • Captain II
  • November 6, 2025

Thanks for your help everyone!

 

Creating new and inserting as ​@Django recommended worked!


Forum|alt.badge.img+7
  • Captain II
  • November 6, 2025

I think with regards to the FieldUpdated, you’re supposed to keep your updates within the current record. 

That doesn’t mean it doesn’t work but the materials say:

To update the field in other detail lines, you will use the RowUpdated event handler.

If you are wondering if you could use a FieldUpdated event handler in this case we do not
recommend this approach, because it can cause data inconsistency. With FieldUpdated, if the
update of the current detail record did not finish—for example, due to a validation error—the changes
in other detail records would not be discarded.


Forum|alt.badge.img+8
  • Author
  • Captain II
  • November 7, 2025

Thanks ​@Django!


Dmitrii Naumov
Acumatica Moderator
Forum|alt.badge.img+7
  • Acumatica Moderator
  • November 7, 2025

@aiwan ​@darylbowman 

There are two different scenarios:

  1. You want to update another field on the same row. In that case you use FieldUpdated event. The idea is that it’ll update the field and in the end it’ll also trigger RowUpdated event for that same record (since you are already in Update routine) and everything will be in order. If something goes wrong during the update of one of the fields, the entire Update will be cancelled and the record reverted to its previous state.
  2. If you want to update a field on another record, you must use RowUpdated event instead. It guarantees that the update came through already and you can update dependent records. If you do it in FieldUpdated, there is a possibility that the update will be cancelled and the initial record rolled back, but your updated dependent record will still stay updated, causing inconsistency.

Hope that clarifies the behavior.


Forum|alt.badge.img+8
  • Author
  • Captain II
  • November 7, 2025

@Dmitrii Naumov 

The training material does cover this for the same row, I can’t remember off the top of my head if it does for other records, but that makes sense, thank you!