A customer reported that a mobile reorder option on a custom page would not persist. They set it, saved, and later found the field back at its default. It looked like a frontend bug, but the evidence led to the persistence path.
My first read: mobile UI bug. The field was rendering correctly. The save button was wired to a JavaScript handler. The page refreshed on submit. I started tracing the frontend.
That was wrong.
the field was saving, just not what it looked like
The symptom was real, but the diagnosis was off. The field value was making it to the server. The POST was landing. The problem was what the backend did with it depending on whether the record already existed.
This custom-page module used separate handlers for ADD and UPDATE. Those paths had been written at different times and had drifted into different field contracts.
The ADD path handled the relevant settings, styles, title, and display-order field. The UPDATE path handled only two positional fields and omitted the setting under investigation.
When an existing custom page was edited, the UPDATE branch omitted the setting under investigation. A page reload was not sufficient confirmation of persistence; a safe read-back of the stored field was needed to distinguish the rendered state from the saved state.
The bug had been there long enough that nobody had traced it to the save path. They had been filing tickets about the UI.
proof before trust
Legacy systems can make path selection difficult to see. A fix may target a handler that looks relevant while a different path, configuration, or include order controls the behavior in practice. That is why evidence after a save matters as much as the proposed code change.
I used a small, access-controlled diagnostic view to verify the fix before closing the ticket. It compared the expected value with the stored field and the rendered result, while exposing only the minimum case data needed for the check. A mismatch became visible without turning the diagnostic into a broad record browser.
That page earned its existence immediately. Without it I would have tested the fix by eyeballing a form reload, which is exactly how the bug hid for this long in the first place.
the fix was symmetry
Once the shape mismatch was clear, the fix was not complicated. I updated the frontend payload builder to include the full field set on both the ADD case and the UPDATE case. Then I updated the UPDATE branch on the backend to accept and persist those fields the same way ADD did.
The change touched the backend save handler, the JavaScript payload constructor, and the verification view. A subsequent authorized test confirmed that the field persisted and rendered as expected.
the question the fix left open
This incident justified an audit question rather than a blanket conclusion: where else do separate create and update paths exist, and which fields lack a clearly tested contract? Those paths should be inventoried and prioritized by risk and observed symptoms, not changed speculatively.
The broader improvement is a shared, explicit payload contract for fields that should behave consistently across create and update operations, with intentional exceptions defined at the serialization layer. That is a refactor and deserves its own scoped work.
For this save path, the verified contract and read-back check now make the behavior observable. In other systems, a non-persisting UI setting can arise from frontend state, API validation, authorization, caching, configuration, or persistence. Split-brain write paths are one high-value hypothesis to test, not a substitute for evidence.
Related
- The Fastest Legacy Hotfix Is Often a Diagnostic: using an evidence path to distinguish data-state and code-path explanations
- The Most Valuable Line in an Agent’s Ruleset: Verify the Fix in the Browser Before Claiming It’s Fixed: confirming the observed result after the underlying fix