Field guide 01 · Persistence

Your form says Saved. So where is the record?

APPFLOWFIX FIELD NOTES · 8 OCTOBER 2026 · 6 MIN READ

A success message is a piece of interface text. A completed task is a result you can reopen. When those disagree, trace one controlled example from input to persisted output before changing more code.

This guide is for an existing React app, including a Lovable project connected to Supabase. It assumes you can run the repository and have authorized access to a safe test environment. It does not ask you to weaken permissions, paste credentials into a prompt, or experiment on customer records.

1. Define the missing result precisely

“Saving is broken” leaves too many possibilities. Write down the actor, actual URL path, action and expected record. For example: “An already signed-in customer opens /requests/new, enters a title, submits once, then reopens /requests. The new request should appear with the same title and Submitted status.” Use a made-up title you can recognize, such as “TEST window repair 08 October.” Do not use personal information as the marker.

Record what actually happens. Is the row absent immediately, visible until refresh, present in the database but absent in the list, or visible only to a different test account? Those are different failures. Include the environment: local development, builder preview and production can be connected to different projects. A result in one environment does not prove a result in another.

Keep this reproduction small. One test account, one record and one browser tab are easier to follow than several parallel experiments. If you cannot reproduce the issue, start with diagnosis instead of promising a repair.

2. Confirm that you are testing the code that actually runs

Before blaming caching, follow the application route to the component it renders. Look for duplicate forms, old pages and similar component names. A change to an unused component can be perfectly valid and completely invisible.

A public Lovable discussion illustrates this trap: the author initially suspected stale updates, then reported finding a duplicate component that was not connected to the route being tested. That is one resolved anecdote, not proof that your app has the same cause. The useful habit is to verify route ownership before another broad prompt.

In a development environment, identify the rendered component through your normal development tools or a temporary harmless label. Remove the label before delivery. Compare the browser URL and the route configuration, including nested layouts and redirects. Write the confirmed component path in your issue note so the next person does not repeat the search.

3. Follow the save across five boundaries

BoundaryQuestionUseful evidence
Input → handlerDid the expected submit handler run once?Controlled reproduction and handler path
Handler → requestWere the intended fields sent?Redacted request shape and field names
Request → responseDid the server accept or reject it?Status and sanitized error category
Response → stored resultDoes the intended record exist?Authorized test-record verification
Stored result → reopened UIDoes the actual list/detail route show it?Refresh and reopen result

Use the browser network panel to inspect the request without copying authorization headers or full payloads into shared tickets. If there is no request, investigate client validation, the event handler and the button state. If there are two requests, inspect duplicate event paths or repeat-click handling. If the request fails, preserve the error category before changing anything.

If the request succeeds but the result seems absent, check the data mapping and the destination environment. A field named title in the interface may have been sent under another property. A list filter may hide newly created rows with the wrong initial status. A local state update may show an object that was never persisted.

4. Interpret Supabase results correctly

Supabase’s JavaScript insert reference states that inserted rows are not returned by default; chaining .select() requests returned rows. A missing returned row is therefore not, by itself, proof that the insert failed. Inspect the error result and verify the intended behavior using authorized test data.

Do not “fix” uncertainty by disabling row-level security or broadening production permissions. If the reproduction points to authorization, ownership or security policy, stop and route that work to an appropriately scoped security review. This workflow-completion guide covers application behavior, not a permission redesign.

Separate write success from list refresh. A successful write may need the application’s normal cache invalidation or refetch path before the list updates. Conversely, forcing a refetch cannot repair a request that never wrote a row. The trace tells you which boundary deserves attention.

5. Make the message follow the result

The interface should show a pending state while the request is in progress, success only after the agreed success condition, and an actionable failure state otherwise. “Something went wrong” is often too vague; “We could not confirm the save. Your input is still here” gives the user a safer next action without revealing internal details.

A timeout creates an important ambiguity: the server might have saved the record even though the browser did not receive confirmation. Decide how the existing application identifies a repeated action. For some tasks, retrying with the same operation identifier is appropriate. For others, the application must look up the result before allowing a new submission. Do not bolt a universal retry rule onto every kind of workflow.

Preserve safe input on recoverable failure. Avoid logging sensitive content just to make debugging easier. A small test fixture and a sanitized error category usually provide a clearer reproduction than a screenshot full of real customer data.

6. Agree on five checks before the change

  1. Valid input: one allowed submission produces the expected record and values.
  2. Invalid input: an empty required field produces an explanation and no record.
  3. Persistence: refreshing and reopening the actual route preserves the result.
  4. Repeated action: repeating the agreed action does not create an unintended duplicate.
  5. Recoverable failure: a controlled request failure preserves safe input and offers the agreed retry behavior.

Then add one neighboring regression: for example, the existing request list still opens an older test record. This is deliberately narrow. Passing these checks does not certify all features, all permissions or the entire application.

Run the relevant checks at a desktop and a narrow mobile viewport when the task is available on both. A button hidden behind a sticky footer can make a correct save handler unusable. Capture the test result, not just a screenshot of a success toast.

7. Leave a useful handoff

Your repair note should identify the original reproduction, the actual cause, the files changed, the five results and the neighboring regression. Include the exact run command and rollback point. List what was not tested, especially production-only integrations or access that was unavailable.

Lovable’s native browser testing can exercise flows and inspect browser evidence, so it may be a useful first route. Its documentation describes limits around authenticated testing with external authentication providers; check the current fit for your setup rather than assuming a builder test covered an authenticated Supabase task.

If you want someone to own this bounded change, AppFlowFix completes one accepted workflow for $799. A runnable repository, safe test data and a clear result are prerequisites. If the cause is too uncertain to price implementation responsibly, the separate $149 diagnosis produces a reproduction and decision memo, not a promised fix.

Sources and limits

Primary documentation checked 7 October 2026. The debugging sequence and acceptance checklist are AppFlowFix’s proposed method.