> For the complete documentation index, see [llms.txt](https://postica.gitbook.io/binding-system-3/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://postica.gitbook.io/binding-system-3/tutorials/surviving-a-rename.md).

# Surviving a Rename

Rename a field fifty bindings point at, and repair them in one pass.

A binding stores its path as text. Rename `health` to `currentHealth` and, in a system with no help, every binding that pointed at it is now pointing at nothing, silently, across scenes you do not have open.

This tutorial breaks a lot of bindings on purpose, redirects them all in one decision, and then covers the one case the tool cannot help with. Better to meet that here than in a release week.

## What you will do

Break fifty bindings with one rename, repair them all in about a minute, then verify that nothing was left behind.

<figure><img src="https://3048705056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLUfBXR02sJ5i0MxwYbaV%2Fuploads%2FwFYW3iZyl1S6GXzRkXPB%2FScreenshot%202026-09-27%20at%2019.03.47.png?alt=media&amp;token=96bf3431-0110-4b55-b932-7b69318da5c1" alt="" width="563"><figcaption><p>The refactoring window, after a rename that broke a lot of bindings</p></figcaption></figure>

**About 20 minutes.**

## What you need

A project with bindings that point at a field you are willing to rename. A throwaway copy is a good idea the first time, purely so you can watch the failure mode as well as the fix.

## 1. Check the safety net is on

**Project Settings ▸ Binding System ▸ Configuration ▸ Refactor Manager**, and confirm **Enable Refactoring** is on.

{% hint style="danger" %}
This matters more than it looks. With refactoring **off**, a [proxy binding](/binding-system-3/overview/proxy-bindings.md) whose member has disappeared is **removed with no prompt and no window**. There is no undo pass afterwards, because there is nothing left to undo from. Leave it enabled.
{% endhint %}

Leave **Prefer Renaming Auto Fix** off for now. You want to see the window this time.

## 2. Break it

Rename a serialized field that bindings refer to. In a `Health` component, `current` becomes `currentHealth`. Save the file and let Unity recompile.

If any of the affected bindings are [proxy bindings](/binding-system-3/overview/proxy-bindings.md) in a scene you have open, a window opens by itself when compilation finishes:

> **Code changes detected** Some members bindings point at are no longer where they were. Decide once per member and every binding of it follows. Nothing is written until you press Apply.

If nothing opens, that is expected and not a problem. An ordinary `Bind<T>` field does not announce itself; it is simply broken and quiet. Step 3 is how you find those, and it is the step that matters.

## 3. Find every binding, not just the loud ones

This is the important step, and it is the one people skip.

Open the refactoring window if it is not already open, from **Configuration ▸ Refactor Manager ▸ Open Refactor Window**, and press **Find more in project**.

That runs a whole-project [validation](/binding-system-3/project-tools/diagnostics/validator.md), which resolves every serialized binding against its source type and collects the ones whose member is gone. Scenes that are not open are opened one at a time so they can be inspected properly, and your original set of open scenes comes back when it finishes.

When it lands, press **Refactor renamed members** in the validator. Every affected member is now a row in the refactoring window, with a count of the bindings waiting on it, wherever in the project they live.

<figure><img src="https://3048705056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLUfBXR02sJ5i0MxwYbaV%2Fuploads%2FwFYW3iZyl1S6GXzRkXPB%2FScreenshot%202026-09-27%20at%2019.03.47.png?alt=media&amp;token=96bf3431-0110-4b55-b932-7b69318da5c1" alt="" width="563"><figcaption><p>One row per missing member, with the count of affected bindings</p></figcaption></figure>

The decision is **per member**, not per binding. Fifty bindings pointing at one renamed field is one decision. Hover the count to see exactly which bindings it covers.

## 4. Replace

Press **Replace** on the row. A picker opens with three branches:

* **Best matches**, members of the same type with a similar name and a compatible value, closest first
* the type the member left, for everything else on it
* **All types**, by namespace, for a member that moved somewhere else entirely

`currentHealth` is at the top of **Best matches**, labelled as an exact name match.

<figure><img src="https://3048705056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLUfBXR02sJ5i0MxwYbaV%2Fuploads%2Fud2RprIMuISXcGux9KRj%2FScreenshot%202026-09-27%20at%2019.05.05.png?alt=media&amp;token=eec69fa0-5a05-489b-a362-ecd9d829cd2e" alt="" width="563"><figcaption><p>The replacement picker, with the renamed member ranked first</p></figcaption></figure>

For a plain rename that is the right answer and it is already first. Pick it.

The other two answers are there when **Replace** is not honest:

<table><thead><tr><th width="200">Answer</th><th>What it does</th></tr></thead><tbody><tr><td><strong>Switch off</strong></td><td>The field was deleted, not renamed. Every binding of it is turned off and keeps the literal value it already holds, so nothing is lost.</td></tr><tr><td><strong>Ignore</strong></td><td>Leave these alone and stop asking. Useful when a member is coming back on a branch you have not merged yet.</td></tr></tbody></table>

Changed your mind about a row? **Undecide** clears it.

## 5. Apply, and understand Close

The footer tells you how many members are still undecided and how many bindings **Apply** will actually change. Read it before pressing anything.

Press **Apply**.

If any row is still undecided you are told first, and can go back or apply the rest. Rows set to **Switch off** are confirmed separately, because that answer changes behaviour rather than repairing it.

Everything it writes goes into **one undo step**. If the result is not what you expected, a single undo puts the project back.

**Close** writes nothing at all. The questions are asked again next time the members come up.

## 6. Verify

Run the [validator](/binding-system-3/project-tools/diagnostics/validator.md) over the whole project again.

A rename that repaired 49 of 50 bindings looks exactly like one that repaired all of them until you look. If the run comes back clean, it is clean; it says how many bindings it checked, which is the number that turns "nothing is wrong" into something you can trust.

Then open the [Dependency Graph](/binding-system-3/project-tools/diagnostics/dependency-graph.md) with the changed type in **Focus** and confirm the connections you expected are still there.

## 7. Turn on the automatic version

Once you trust it, go back to **Configuration ▸ Refactor Manager** and turn on **Prefer Renaming Auto Fix**.

Now a rename carrying `[FormerlySerializedAs]` is followed silently, through a chain of renames if there is one, and no window appears. Ambiguous cases still stop and ask, which is the behaviour you want: silence when it is obvious, a question when it is not.

## What just happened

**Two different things find broken bindings, and they are not equivalent.** A proxy binding notices when it is loaded and cannot build its accessor, which is why the window can open by itself. An ordinary `Bind<T>` field notices nothing at all. The validator is what covers the second case, because it reads the serialized data rather than waiting for something to fail.

**Decisions are keyed by member, not by binding.** That is why one row covers fifty bindings, why a decision survives to a scene you open next week, and why the count on a row can grow as more bindings are found.

**They are remembered.** An answered member is written to `Library/bs-refactors.json` alongside the other editor caches, so the same rename is not asked about twice. A decision is dropped when the member it was about comes back. The settings panel lists every one as a rule, and forgets one or all of them by hand.

**`[FormerlySerializedAs]` is still the right tool, and it composes with this.** The attribute keeps the **value** across a rename, because that is Unity's serializer. Refactoring keeps the **bindings**. With **Prefer Renaming Auto Fix** on, the attribute drives both.

## What it cannot repair

One category, and you want to know about it in advance.

**A modifier or converter class that you rename or move.** Modifiers and converters are stored with `[SerializeReference]`, which persists the assembly, the namespace and the class name. Rename `GammaModifier`, change its namespace, or move it into a different assembly, and every instance already saved in a scene, prefab or asset is orphaned.

Refactoring cannot follow that. It redirects paths, and a modifier's type is not a path, so there is nothing for it to rewrite.

The [validator](/binding-system-3/project-tools/diagnostics/validator.md) does at least **report** it, as *Modifier type is missing*, naming the type that used to be there and the binding it was on. That turns a silent data loss into a list. The repair is manual: pick the modifier again on each row, or remove the slot.

<table><thead><tr><th width="330">Change</th><th>Is it safe</th></tr></thead><tbody><tr><td>Rename a modifier or converter's <code>Id</code></td><td><strong>Safe.</strong> The <code>Id</code> is a menu label and a registry key. It is not written into saved data.</td></tr><tr><td>Rename the class, change its namespace, or move it to another assembly</td><td><strong>Orphans every saved instance.</strong> Reported by the validator, not repairable automatically.</td></tr><tr><td>Add, remove or rename a <em>field</em> on the modifier</td><td>Ordinary Unity serialization. <code>[FormerlySerializedAs]</code> applies as usual.</td></tr></tbody></table>

This is why the package's own deprecated `StringFormatModifier` and `StringConcatModifier` are still sitting in their original files with their original names, unregistered so they cannot be added anew, rather than being deleted. The comment in the source says so in as many words. Treat a shipped modifier's class name and namespace as part of your data format.

## Try changing this

**Turn refactoring off and rename something a proxy binding points at.** In a throwaway copy. The proxy is removed with no prompt. Doing this once is the cheapest possible way to remember to leave the setting on.

**Rename a class rather than a field.** Bindings that referred to the old type are reported by the validator as *Source type no longer exists*, which is a different problem from a missing member and has a different fix: repoint the source, or switch the binding off.

**Turn on Refactor Unity Classes.** Members of Unity's own types are then handled too. That is the setting that saves you when an editor upgrade renames something in `UnityEngine`.

**Rename a modifier class on purpose.** In a throwaway copy, with a scene that uses it open. No refactoring window appears, and the modifier row is empty. Then run the validator and watch it name the type that went missing. That contrast is the thing to remember.

## Related pages

* [Refactoring](/binding-system-3/project-tools/diagnostics/refactoring.md): the window, the settings, and what it handles.
* [Bindings Validator](/binding-system-3/project-tools/diagnostics/validator.md): what finds the broken bindings in the first place.
* [Auditing a Project Before Release](/binding-system-3/tutorials/audit.md): the full pass, in order.
* [Dependency Graph](/binding-system-3/project-tools/diagnostics/dependency-graph.md): confirming the connections survived.
* [Reserializer](/binding-system-3/project-tools/diagnostics/reserializer.md): the neighbouring problem, changing a field's type to or from a bind type.
