DEV Community

Al hasib Tamim
Al hasib Tamim

Posted on Originally published at clearcutover.com

Why SyteLine Says "Row Has Been Modified by Another User" (and How Optimistic Concurrency Works)

In Infor SyteLine (CloudSuite Industrial) and the Mongoose framework, few error messages trigger more user frustration than:

"This row has been modified by another user since you began editing it."

Users frequently submit urgent tickets insisting: "I'm the only person working in this site today! Why is it telling me someone else changed it?"

Here is an architectural breakdown of what is actually happening at the database level, why the error is by design, and how to track down the true culprit.

How Optimistic Concurrency Works Under the Hood

SyteLine uses optimistic concurrency control rather than pessimistic locking.

When a user opens a customer order, item, or PO line in a WinStudio form or IDO:

  1. The framework loads the record along with two critical audit columns: RowPointer (a unique surrogate GUID) and RecordDate (the timestamp representing the row version).
  2. The client application keeps that specific RecordDate in local memory during the editing session.
  3. No database locks are held while the user looks at the form. This is intentional: holding exclusive or shared database locks while an operator walks away for lunch would grind the entire ERP to a halt.

When the user finally clicks Save, the IDO runtime executes a parameterized UPDATE statement that looks conceptually like this:

UPDATE coitem_mst
SET qty_ordered = @new_qty,
    RecordDate = GETDATE(),
    UpdatedBy = @user
WHERE RowPointer = @rowpointer
  AND RecordDate = @original_record_date;
Enter fullscreen mode Exit fullscreen mode

Notice the crucial predicate: AND RecordDate = @original_record_date.

  • If the row in SQL Server still matches the timestamp loaded into memory, the UPDATE affects 1 row. The save commits cleanly.
  • If anything changed that row in the meantime, SQL Server's RecordDate has advanced. The WHERE clause evaluates to false, affecting 0 rows.
  • The framework detects 0 rows updated and raises the "modified by another user" error to prevent a lost update.

The Real Culprits (Why It Happens When "Nobody Else Is Editing")

If a single user is editing alone and hits this error, the cause is almost never another human. It is one of these four automated mechanisms:

1. "Your Own Session Changed It" (The Post-Save Event Handler Trap)

This is the most common self-inflicted defect in custom forms and IDO extension classes:

  • A custom after-save event handler or stored procedure updates a status flag or recalculates a total on the same row immediately after the initial save.
  • SQL Server updates RecordDate to reflect the handler's change.
  • The user's client form, however, is still holding the pre-save RecordDate. On the very next click or subsequent save, the save fails immediately.

2. Background Tasks & Utilities

Background processes running under the Infor Framework TaskMan (order posting, EDI transaction imports, shipping utilities) update records asynchronously. If an operator leaves an order open for hours, a background run can easily touch that order line.

3. Direct SQL Scripts or Unofficial Jobs

SQL Agent jobs or legacy triggers written to "patch" data directly in SQL tables without routing through the Mongoose IDO layer will bump RecordDate silently, catching client users off guard.

4. Custom IDO Round-Trip Failures

When building custom REST integrations or WinStudio forms, failing to round-trip RecordDate and _ItemId properly on UpdateCollection calls will cause optimistic concurrency checks to fail every time.

How to Find the Culprit in Production

When a user reports this repeating on a specific form or order, don't guess:

  1. Check the Audit Columns: Run a read-only query on the affected record:
   SELECT RowPointer, RecordDate, UpdatedBy, CreateDate, CreatedBy
   FROM co_mst
   WHERE co_num = 'ORD12345';
Enter fullscreen mode Exit fullscreen mode

Inspect UpdatedBy and RecordDate. If UpdatedBy shows a service account or background process rather than a human username, you've identified the offending job.

  1. Check Background Task History: Match the RecordDate timestamp against the completion timestamps in Background Task History or the Windows Event log.

What NOT to Do

  • Never bypass the check via direct SQL UPDATE: That destroys data integrity and bypasses Mongoose business logic.
  • Never teach users to blindly re-save: Re-saving without refreshing means they are overwriting changes from other processes without reviewing what changed.

Originally published with full troubleshooting workflows at Clear Cutover.

Top comments (0)