Metadata
| Field | Value |
|---|---|
| Article type | Troubleshooting (How-to) |
| Plugin slug | mam-main |
| Applies to plugin version | 26.29.15 (verified build) |
| Category | Troubleshooting |
| Audience | PHP developer |
| Last verified | 2026-06-03 (draft — see Verification) |
Goal
You changed something that affects how a form’s fields are output to the mobile app — a custom field-type transform, a per-field special-handling toggle, theme colors, or any setting that feeds the form’s transformed JSON — and the app is still rendering the old form. This article shows you how to invalidate the form cache correctly so the next phone-data pass rebuilds the form, and explains why you should not simply delete the cached option by hand.
If you are still building the change itself, see Custom field types and Form cache and invalidation in the Plugin Reference. This article is for the specific “I made the change but the app shows the old field” symptom.
Why this happens
The phone-data pipeline rebuilds the mobile JSON on every app load. Running every form through Gravity Forms’ full schema fetch and the mam-suite per-field-type transformation chain on every cold launch is expensive, so mam-main caches the transformed form shape. Cache hits skip the entire transformation chain — which is exactly why a stale cache keeps serving the old field after you have already changed the code or setting that produces it.
mam-main stores the built payload and regenerates it only when a global “stale” flag is set. Saving any post sets that flag, so editing a form in Gravity Forms rebuilds it. But a setting written outside a post save — an AJAX-written per-field toggle, or code (a transform filter) that the cache cannot see at all — never sets the flag, so nothing tells the cache it is stale. The app keeps getting the cached shape until something forces a rebuild.
Prerequisites
- PHP developer access to the site (a code path that runs in WordPress: a plugin, a mu-plugin, or WP-CLI
eval). mam-mainactive. The form cache lives inmam-main; it is not owned by Gravity Forms.- The form id of the affected form. In Mobile App Manager → Forms the form id matches the Gravity Forms form id.
- You have already made and saved the underlying change (the filter, the special-handling toggle, the color setting). This article only forces the rebuild; it does not make the change for you.
Steps
1. Confirm it is actually a stale cache
Match your symptom against the known stale-cache cases:
| Symptom | Likely cause |
|---|---|
| Admin updated a form, app still shows the old version | Cache wasn’t invalidated for that form id |
| New custom field type added, app shows the old GF default | Cache wasn’t rebuilt after the new transform filter registered |
| Per-field special-handling toggle changed, app still shows old behavior | The toggle isn’t part of the cache key |
| Theme colors changed, forms still show old colors | The color settings aren’t part of the cache key |
If your symptom isn’t in this table, the problem is probably upstream of the cache (the transform filter isn’t firing, or the mobile client doesn’t recognize the field type). Stop here and check those before forcing a rebuild.
2. Prove it with a one-off rebuild
Before you wire anything permanent, prove the cache is the culprit by forcing a single rebuild and reloading the app. The supported, code-grounded way to force the next phone-data pass to rebuild is the cache-clear action that mam-main already listens for:
do_action( 'tsl_clear_json_cache' );
This sets the global “regenerate all cached JSON” flag (the same flag a post save sets), so the next app load rebuilds the payload from scratch. Reload the app.
- If the app now shows the new field: confirmed stale cache. Go to step 3 to fix it permanently for that form.
- If the app still shows the old field: this is not a cache problem. Re-check that your transform filter fires and that the mobile client supports the field
type.
Avoid hand-editing the cached-JSON store (the
tsl_local_app_cached_jsontable) or flipping thetsl_mam_clear_all_cached_jsonsoption by hand as your diagnostic. Fire the action above instead — it is the supported entry point, and it sets the flag exactly the way a post save does.
3. Invalidate the specific form (preferred)
mam-main does not expose a form-scoped invalidation API — every invalidation regenerates the whole payload on the next pass. What you can control is when the rebuild is triggered. For a fix you ship, fire the clear from the write site of whatever changed:
// Fired from the code path that saved your setting.
do_action( 'tsl_clear_json_cache' );
Put this in the same code path that saves the setting: when an admin (or your code) writes the per-field special-handling toggle, the color, or whatever feeds the field output, fire the clear in the same breath. That guarantees the change and the rebuild trigger can never drift apart.
4. Only invalidate everything when you must
Because invalidation is global, the clear you fire in step 3 already rebuilds every form on the next pass. The action is the only mechanism mam-main exposes:
// Regenerates all cached payloads on the next pass.
do_action( 'tsl_clear_json_cache' );
Fire it sparingly. It forces every form to rebuild on the next phone-data pass, multiplying app-launch latency until the cache rewarms across all forms. Never wire it into a request path that runs on every app load.
5. Fix the root cause: put the setting in the cache key
A one-off clear fixes the symptom once. The durable fix is to make the setting’s own save path fire the clear, so changing it automatically marks the cache stale. Settings saved through a normal post save get this for free (any save_post sets the flag); settings saved another way — an AJAX handler, a custom options screen — do not.
If you find yourself clearing by hand every time a particular toggle changes, that toggle’s save path isn’t firing the clear. Saving a setting that affects form output without triggering an invalidation is the single most common source of these stale-cache bugs. See Form cache and invalidation for the full list of triggers that already fire it.
Verification
After invalidating:
- Reload the app cold and confirm the form’s mobile JSON reflects the new field output (the new
type, color, or special-handling behavior). - Change the underlying setting again and confirm the app updates without a manual invalidate. If it still needs a manual invalidate, the setting is not in the cache key — go back to step 5.
- Confirm you did not leave a
do_action( 'tsl_clear_json_cache' )in a hot path. A full clear on every request defeats the cache entirely.
Gotchas
- Don’t hand-edit the cache store or the stale flag. Use the clear action — it sets the flag the supported way. Poking the
tsl_local_app_cached_jsontable or thetsl_mam_clear_all_cached_jsonsoption by hand invites inconsistent state. - Every clear is global.
tsl_clear_json_cacherebuilds every form and spikes launch latency. Fire it only from a setting’s save path, never on a hot request path. - The cache can’t see your filter. A new build-time transform filter does not invalidate anything on its own — registering a filter is invisible to the cache. You must invalidate (or change a key input) for the rebuild to pick it up.
- A still-stale app after invalidating is not a cache bug. Check that the transform filter fires and that the mobile client recognizes the field
type. New field types need a coordinated mobile release. - The form cache is owned by
mam-main, not Gravity Forms. Saving the form triggers a rebuild via thesave_posthook, but settings written outside that path won’t unless you invalidate.
Related
- Form cache and invalidation (Plugin Reference,
mam-main) — what the cache stores and the full invalidation-trigger list. - Custom field types (Extending MAM Suite,
mam-main) — the two-hook round trip; step 5 there is “invalidate the form cache.” - Forms manager overview — where the cache sits in the phone-data pipeline.
- Form submission lifecycle — the app-to-server side of the round trip.
What’s next
Once the form rebuilds correctly, audit any other settings you own that feed form output. If a setting changes the transformed shape and isn’t in the cache key, it will produce this same bug for the next person. Fixing the cache key once is cheaper than triaging the stale-cache report again.
