Changing a field group safely
7 min read
Every field is a column, so editing a saved field group changes a real database table. The plugin does this with a few safety rules so that you do not lose values by accident.
The safety rules
Rule | What it means |
|---|---|
Table first, definition second | On save, the table is altered first. Only when that worked is the field group definition stored. Definition and table cannot drift apart because of a failed save. |
All or nothing | If one step fails (for example a new unique index meets duplicate values), the steps already done are undone and the message ends with |
Removing never deletes data | A removed field's column stays as a leftover column. |
Risky conversions keep a backup | Before a conversion that could lose data the old values are copied to a |
Large tables change in the background | See Large tables. |
What each change does
You change | What happens to the table | Values |
|---|---|---|
Add a field |
| New column, empty (or the default). |
Rename a field's key |
| Kept. |
Change label, instructions, placeholder, width, display settings, conditional logic, location, group settings | Nothing in the table. | Kept. |
Change the default, Required, SQL column options, Unique |
| Kept. |
Change the type to a compatible one (for example Text to Text area) |
| Kept. |
Change the type to a risky one (for example Text to Number) | A backup column | Converted; originals in the backup. |
Add or remove Add index |
| Kept. |
Remove a field | Nothing. The column becomes a leftover column. | Kept in the table. |
Add the first location rule to a group that had none | Adds the | n/a |
Remove every location rule | Nothing: | Kept. |
Rename or retype a sub-field inside a Group or Repeater | The container's column is copied to | Kept; originals in the backup. |
Reorder fields | Nothing in the table. | Kept. |
After a save the plugin reports what it did. A rename shows renamed, a type change shows type: text→number, and backups show as migration_backups. For example, after converting a Text field name to Number the editor shows A type change could lose data, so the old values were copied to: name__bak. Check the converted values, then delete the backup columns under Table health.
Renaming a field
- Change the field's Field key (SQL column name). The row warns
Key rename will run SQL RENAME COLUMN. - Save. Values are kept.
- Update templates, shortcodes and code that use the old key.
Through the REST API a rename is the same uid with a new key (see Create a field group).
Changing a field's type
The dialog This type change can lose data appears for risky changes. What you can lose depends on the direction:
Direction | Risk |
|---|---|
To a numeric type | Non-numeric values become |
To a JSON type | Values that are not valid JSON are rejected or become |
From a JSON type to a text or number type | JSON objects and arrays become their string form and may be cut off. |
From | Longer values are truncated. |
Your three choices:
- Cancel: nothing changes.
- Convert with a backup: the old values go to
{key}__bakfirst. After saving, check the converted values. When you are happy, delete the backup column under Table health › Leftover columns › Remove from DB. - Create a new field instead: adds a second field with the new type and leaves the old column alone. This is the recommended path when you want to migrate values by your own rules (copy them with a script, then remove the old field).
If a backup column with that name already exists, the next one is named {key}__bak_2, {key}__bak_3 and so on.
See Table health for how to review and remove backup columns.
A type change of an indexed field also clears the index if the new type cannot be indexed. If you save through the REST API, send "indexed": false yourself in that case, otherwise the database refuses (BLOB/TEXT column ... used in key specification without a key length) and nothing is changed.
Removing a field
The field leaves the editor and edit screens; its column keeps its values. The column appears in Table health under Leftover columns (Table differences panel) and in the REST schema response as orphan_columns.
From there you can:
Action | Effect |
|---|---|
Import as fields | Adds the column back as a new field; the type is guessed from the column's SQL type: numeric types become Number, |
Remove from DB | Permanently drops the column and its values after a confirmation. Only leftover columns can be dropped; a column a field uses is refused ( |
Reusing the name of a removed field
If you add a new field whose key equals a leftover column, saving first stops with the dialog These names hold saved values:
A field you removed earlier used the same name, and its values are still in the database. Choose what the new field should do with them.
Choice | Result |
|---|---|
Use the saved values | The new field shows the values the old field saved (the column is converted to the new field's type if needed). |
Start empty | The old values move to a backup column you can delete later; the new field starts empty. |
Click Save changes in the dialog to apply your choice, or Cancel to go back. (REST: the save answers 409 with code wpmcf_orphan_columns and a list of columns; resend the request with "orphan_columns": { "key": "reclaim" } or "fresh".)
Large tables
Altering a table with many rows can take longer than a web request. When the table has about 100,000 rows or more (an estimate), the change is queued and runs in the background through Action Scheduler. Changes that rewrite stored Group or Repeater values start earlier, from about 5,000 rows, because that work runs row by row in PHP. Developers can change the first threshold with the wpmcf/fields/schema_background_rows filter.
While a change is queued or running:
- The editor shows Applying database changes:
This table is large, so the changes run in the background. The site uses the previous version until they finish. You can leave this page.and the card shows an Updating badge. When it finishes:The database changes are done. - The site keeps using the previous definition until the change completes.
- Values saved meanwhile are kept and written once the change is done (renamed fields are mapped to their new columns).
- Save changes is disabled and the API answers
409(wpmcf_schema_busy):Database changes for this field group are still being applied. Save again when they are done. - You can cancel a queued change (not a running one) with
DELETE /wpmcf/v1/field-groups/{key}/schema-job; a failed change can be dismissed the same way (the Dismiss button).
If the job fails the editor shows The last changes could not be applied with the database message, and The site still uses the previous version of this field group. A job that is still "running" after 15 minutes is treated as interrupted: The database change was interrupted before it finished. Review Table health in the field group, then save again. Action Scheduler must be able to run (WP-Cron or a real cron); see Troubleshooting.
Warnings you may see on save
Warning | Meaning |
|---|---|
| A reminder to use Group fields. |
| Eight or more indexes slow writes. More than 20 is an error. |
| Information about text indexes. |
| Index requests on JSON types are ignored; query JSON values by path instead. |
Troubleshooting
Problem | Fix |
|---|---|
| Read the database message: duplicates for a unique index, a column type that cannot hold existing values, an index key too long. Fix the data or the setting and save again. |
A new unique index fails | The column holds duplicates; clean them first. |
The Updating badge never goes away | Action Scheduler is not running. Check Tools › Scheduled Actions (hook |
After a sub-field rename I see | Expected: renaming or retyping sub-fields copies the container column first. Delete the backup under Table health when you have checked the values. |
The leftover column is not offered when I add a field | The names must match exactly. Rename the field or use Import as fields. |
Still stuck? Contact support