Case 01
Pending change vs the server record
Problem
A user edits a task or a note on a plane. The list shows the new text immediately. When the connection returns, the server rejects the write: someone else updated the same record, permission was revoked, or the record no longer exists. The first version does not merge field by field. The rejected change is dropped and the screen shows the server record again. Calling this “save failed, try again” leaves the wrong record on screen.
Context
CoBu writes offline. The source of truth is the last record the server accepted. An offline edit is not written over that row. When the list is read, the pending patch is applied on top. If the write version does not match, the patch is deleted in the same operation. A late list response does not overwrite a newer sync that arrived in the meantime.
What I owned
[I split pending, accepted, and rejected on the list row.]
Interface decisions
A row has three states. Pending: the text the user wrote stays, there is a small pending mark, there is no second save button. Accepted: the mark goes away, the text is what the server wrote. Rejected: the text returns to the server state and the reason is said. Three rejections are not the same sentence. If permission was revoked, there is no retry, the action closes and permission is refreshed. If the record is gone, the row does not stay as a ghost in the list. If versions collided, the user’s text is not kept. The screen says the server won. A second copy of the same record is not stored. Otherwise the rejected text is treated as the real record on the next open.
What I chose not to do
I did not merge two conflicting texts field by field. In the first version there is no rule for which field wins. There is also no silent retry. A permission rejection is not a network error. Retrying a few times gives the user hope and grows the same 403.
Quality
Edit in airplane mode, the list shows the new text. Open the connection, the server returns a version mismatch, the text returns to the old state and the explanation appears. At the same time the list refreshes while sync arrives. The late response does not write over the new row. [I verified these three paths on this record type.]
Result
The user sees their change immediately. If the server rejects it, the screen does not insist on the wrong record.
Next
[Show the rejected text as a draft for a short time. Say which field dropped. Merge only arrives if the product chooses that rule.]