> 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/audit.md).

# Auditing a Project Before Release

Every binding in the project, swept in the order that finds trouble.

## Auditing a Project Before Release

A binding that is wrong does not throw. It sits there, correctly configured except for the one part nobody filled in, and does nothing. In the editor you probably never noticed, because the value it should have been driving already looked right.

This is a pass to run before a release, or before handing a project to someone else. It is two passes really, and they answer different questions:

<table><thead><tr><th width="290">Pass</th><th>What to use</th></tr></thead><tbody><tr><td><strong>What is broken</strong></td><td>The <a href="/binding-system-3/project-tools/diagnostics/validator.md">validator</a>. Resolves every binding the way the runtime would and reports the ones that cannot work.</td></tr><tr><td><strong>What is half built</strong></td><td><a href="/binding-system-3/project-tools/diagnostics/dependencies.md">Bindings Dependencies</a>. Every binding that exists, with the structurally incomplete ones grouped together.</td></tr></tbody></table>

Run them in that order. The validator is slower and finds more, so it is the one to start while you make coffee.

### What you will do

Find every binding in the project that cannot work, repair or redirect the ones that can be, then read the ones that were never finished.

<figure><img src="https://3048705056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLUfBXR02sJ5i0MxwYbaV%2Fuploads%2F21Qf752LfgnGaAdI0WZS%2FScreenshot%202026-09-27%20at%2011.48.26.png?alt=media&amp;token=dc555424-fb1f-4cef-b3d1-da3aff511569" alt=""><figcaption><p>A project-wide audit, grouped into sections that act as a checklist</p></figcaption></figure>

**About 30 minutes on a real project**, most of it waiting for the first pass.

### What you need

A project with bindings in it. Ideally a real one, because the point of this tutorial is what it finds.

***

## Pass one: what is broken

### 1. Start the validation

**Window ▸ Binding System ▸ Validate Whole Project**, and confirm.

It asks because it opens scenes. Every scene that is not already open is opened one at a time so its bindings can be inspected properly, and put back exactly as it was. Nothing is saved and nothing is changed, so unsaved work is never at risk, and a scene you have open is read as you see it rather than as it was last written.

<figure><img src="https://3048705056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLUfBXR02sJ5i0MxwYbaV%2Fuploads%2FoJXvmtZVnM7nfknlcjcP%2FScreenshot%202026-09-27%20at%2011.50.41.png?alt=media&amp;token=a8010b52-ea21-42fa-91d4-3397a876a8e5" alt="" width="563"><figcaption><p>The whole-project run, with the asset it is on and a stop button</p></figcaption></figure>

It can be stopped at any point, and stopping still produces a report of everything reached, marked as incomplete.

{% hint style="info" %}
If you would rather it left your scenes alone, turn off **Open closed scenes** in the options panel, which slides in from the button beside the scope dropdown. Closed scenes are then read from their files instead: broken paths, missing types and direction conflicts are still found exactly, converters and modifiers are not looked at. Findings from such a scene say so, and the status bar counts them.
{% endhint %}

### 2. Read the errors

The summary chips split the result three ways. Start with **errors**; click the warning and hint chips to hide the rest while you do.

Findings are grouped by problem rather than by asset, which is the right way round: one renamed field breaks a lot of bindings, and the group header states it once with a count.

Select a row. The detail panel explains what is wrong, and for a broken path it shows the path broken into segments with **the segment that stopped the walk highlighted**. On a five-segment path that is the whole answer.

**Show me** takes you to the actual bound field, opening its scene if needed.

### 3. Repair what is safe, in bulk

Press **Repair safe findings**.

That applies, in one undo step, every repair that cannot lose any of your work: switching off a binding that could never resolve, removing an empty modifier slot, narrowing a direction that was never going to work. You are told how many before anything happens.

Destructive repairs are deliberately not in it. Clearing a source loses the reference; deleting a proxy loses the binding. Those stay one click at a time, in the detail panel.

### 4. Hand the renames to Refactoring

Press **Refactor renamed members**.

Every finding about a member that was renamed or moved goes to the [refactoring window](/binding-system-3/project-tools/diagnostics/refactoring.md), which asks **once per member** where it went, then redirects all of its bindings at once. See [Surviving a Rename](/binding-system-3/tutorials/surviving-a-rename.md) for that window in detail.

### 5. Re-run, and read the count

Validate the whole project again.

What matters is not that the list is empty; it is the sentence next to it saying how many bindings were checked and across how many assets. That number is the difference between "nothing is wrong" and "nothing was looked at", and the two look identical without it.

Errors gone? Now read the **warnings**: an empty modifier slot, a modifier that never runs, a bind variable nothing declares. None of them stop a binding working, and all of them mean somebody's intent did not survive.

The **hints** are performance, not correctness. Take them to the [Bindings Monitor](/binding-system-3/project-tools/diagnostics/bindings-monitor.md), which is the tool that actually measures cost, and to [Finding the Binding That Costs You Frames](/binding-system-3/tutorials/find-the-cost.md).

***

## Pass two: what is half built

The validator finds bindings that are wrong. It does not flag a binding that is simply unfinished, because an empty one is not an error, it just does nothing. That is this pass.

### 6. Make sure the scanner can see anything

Open **Project Settings ▸ Editor ▸ Asset Serialization** and check that **Mode** is **Force Text**.

The scanner reads scene, prefab and asset files as YAML from disk, which is how it can report on scenes nobody has open. Under **Force Binary** or **Mixed** it can see nothing on disk, and the package quietly routes you to the older window instead, which walks live objects only.

{% hint style="info" %}
If your project is on Force Binary for a reason, this pass still works, but only over what is currently loaded. Open the scenes you care about before starting, and read the rest as a per-scene pass rather than a project-wide one. Pass one is unaffected: the validator loads objects, so it does not need Force Text.
{% endhint %}

### 7. Open the project-wide list

**Window ▸ Binding System ▸ Bindings Dependencies**.

If the scope area at the top has anything in it, press **Clear scope**. An audit starts project-wide.

Leave **Scene**, **Prefab** and **Asset** all enabled. Leave **Build only** off for now, deliberately: the first look is about what exists, and narrowing too early hides bindings in scenes somebody forgot to add to the build.

The list groups itself into five sections, and the order is the audit.

### 8. Read No Sources

**No Sources** is direct-source bindings with no source object set. Expand it.

Every row here is a binding that will read nothing and write nothing when the game runs. There are three reasons a row is in this list, and they have different fixes:

<table><thead><tr><th width="290">Why it is here</th><th>What to do</th></tr></thead><tbody><tr><td>Somebody started it and stopped</td><td>Finish it, or right click the field and <strong>Disable Binding</strong>. A half-built binding is worse than none, because it looks configured.</td></tr><tr><td>The source object was deleted</td><td>Repoint it, or delete the binding. Check whether a <a href="/binding-system-3/tutorials/surviving-a-rename.md">rename</a> caused it before doing either.</td></tr><tr><td>It genuinely needs no source</td><td>Fix it properly: set the path to <strong>Nothing</strong> in the bind path menu, which marks it as deliberately sourceless. It then moves to <strong>Unbound</strong> and stops appearing in this list.</td></tr></tbody></table>

That third row is the one worth internalising. If a sourceless binding is intentional, say so in the data. Otherwise every future audit rediscovers it, and eventually somebody "fixes" it.

Click any occurrence and the window resolves it back to the live object and pings it, so you land on the actual bound field rather than on its asset.

<figure><img src="https://3048705056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLUfBXR02sJ5i0MxwYbaV%2Fuploads%2Fzy6gJvzwljWPFuN6qKZy%2FScreenshot%202026-09-27%20at%2018.13.42.png?alt=media&amp;token=e84203c1-c2e0-4a25-bc1f-5dc2cd76d6d9" alt=""><figcaption><p>The No Sources section, expanded to its occurrences</p></figcaption></figure>

### 9. Read No Paths set

Same idea, other half: the source is set and the path is empty. Somebody dragged an object onto a row and never picked the member.

These are usually quicker to fix than **No Sources**, because the source tells you what was intended. Click through, open the bind path menu, pick the member.

### 10. Now turn on Build only

Tick **Build only** and read the same two sections again.

The list shrinks to bindings reachable from scenes actually in the build. Rows that survive are the ones that ship broken. Rows that disappear were in scenes outside the build, and are marked *Only used in scenes outside the current build scope* when you look for them.

This is the ordering that matters: **find everything first, then find out what ships**. Doing it the other way hides the case where the real bug is that a scene is missing from the build settings.

<figure><img src="https://3048705056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLUfBXR02sJ5i0MxwYbaV%2Fuploads%2FYdrhBMH1QIIHshxCw5pF%2FScreenshot%202026-09-27%20at%2018.15.07.png?alt=media&amp;token=302976c1-a22d-4dc1-8b4e-e9db8f870051" alt=""><figcaption><p>Build only, narrowing the audit to what actually ships</p></figcaption></figure>

### 11. Skim Unbound, so you do not undo somebody's intent

**Unbound** holds constant `Bind<T>` wrappers, the ones somebody unbound and left as a plain value, and bindings explicitly marked as needing no source. The rows are visually muted, because they are not problems.

Read it anyway, once. It is where you find out that the value you were about to go and wire up is deliberately a constant, and it is where a binding somebody unbound while debugging and forgot to re-bind will be sitting.

### 12. Sweep Source objects for the wrong kind of reference

**Source objects** is every direct-source binding that does have a source. This is the large section, and it is not a problem list, so do not read all of it.

Do use its source pills. Click one and it pings the source in the Hierarchy or the Project window. What you are looking for is bindings pointed at something that will not be there at runtime: a scene-only object referenced from a prefab that gets instantiated elsewhere, or a debug object that is not in the build.

{% hint style="success" %}
The two most common versions of that mistake are found for you in pass one. A binding across two scenes, and an asset pointing at a scene object, are both reported by the validator as errors, because neither reference survives being saved.
{% endhint %}

For a targeted version of the same question, right click any object and choose **Binding ▸ Show Dependencies**, or press **Ctrl** or **Cmd** + **Shift** + **D** with it selected. The window opens already scoped to it. Drop a folder into the scope area to audit one feature at a time. **Binding ▸ Validate Bindings** on the same selection is the pass-one equivalent.

***

### What just happened

**Two tools, two questions, and the difference is what each can see.** The dependencies window reads the serialized data, so it can report on scenes nobody has open, and it can only report what is visible in the data itself: an empty source, an empty path. The validator resolves each binding against its types, so it finds a path that stopped resolving three components deep, a write to a member with no setter, a converter whose class is gone. A binding like that looks perfect to the first tool.

**The sections are the audit.** They are not five ways of slicing one list, they are five different questions, and only the first two are usually problems. Grouping by *kind of thing* rather than by asset is what turns a few thousand bindings into a readable pass. The validator does the same thing with problems: one row per problem, not per binding.

**Build only is a second question, not a filter you leave on.** It answers "does this ship", which is only useful once you already know "does this exist". A row that vanishes when you tick it is telling you something about your build settings, not about the binding.

**Nothing here reports a wrong value.** Both passes find bindings that are structurally wrong or structurally incomplete. A binding pointing confidently at the wrong member is valid and looks perfect in both. For that you need [Live Debug](/binding-system-3/project-tools/diagnostics/live-debug.md) at runtime, or [Path Value Preview](/binding-system-3/project-tools/diagnostics/path-value-preview.md) while authoring.

### Try changing this

**Break one on purpose, two different ways.** Enable a binding on any field and leave it empty: it appears under **No Sources** in pass two, and as *Nothing to bind to* in pass one. Now bind it properly and rename the member it points at: pass two shows nothing at all, and pass one names the exact segment that broke. That contrast is the whole model.

**Put the validator on your build machine.** It runs headless, exits non-zero when there are errors, and can write its report to a file:

```bash
Unity -batchmode -quit -projectPath <project> \
      -executeMethod Postica.BindingSystem.Validation.BindValidationBatch.ValidateProject
```

An audit you have to remember to run is an audit that stops happening.

**Scope to a folder.** Drag a feature folder from the Project window into the dependency window's scope area, or select it and choose **Binding ▸ Validate Bindings**. Both narrow to that feature, which is the right granularity for a code review rather than a release.

**Run it on a branch you did not write.** This is the pass that tells you what state somebody else's feature is actually in, and it takes less time than reading the diff.

### Related pages

* [Bindings Validator](/binding-system-3/project-tools/diagnostics/validator.md): every control on the window, and the full catalogue of what it checks.
* [Bindings Dependencies](/binding-system-3/project-tools/diagnostics/dependencies.md): every control on that window, including the legacy fallback.
* [Refactoring](/binding-system-3/project-tools/diagnostics/refactoring.md): redirecting the bindings of a member that moved.
* [Surviving a Rename](/binding-system-3/tutorials/surviving-a-rename.md): what to do when the audit finds a lot of broken paths at once.
* [Finding the Binding That Costs You Frames](/binding-system-3/tutorials/find-the-cost.md): the performance pass, which is a different tool.
* [Error Visualization](/binding-system-3/project-tools/diagnostics/errors.md): how a broken binding presents itself in the Inspector.
