# Reading the summary

When a patch does not do what you expected, the summary tells you why. After every patch run, PatchManager writes a report to a file called `pm_summary.log` in the game's working directory (the folder the game runs from). It lists what ran, what was skipped, what errored, and what was removed before it could run. This is your primary debugging tool. Get in the habit of opening it whenever a patch misbehaves.

PatchManager patches separately for each [feature set](/doc/campaign-features-9YIewcIArR). It patches for the set of the main menu at boot, and for the set of each campaign when the campaign loads. `pm_summary.log` has one part for each set that PatchManager patched for in this session. Each part starts with two lines:

* A `==== Feature set <id> ====` line.
* A `Features:` line that lists the features of the set.

The part with the `(active)` mark is the set that the game runs now. Make sure that you read the part for the campaign that you tested. PatchManager also keeps the part of each set as `summary.log` in the folder of that set in the [patch cache](/doc/caching-and-invalidation-QifFi4oev9).

## What is in it

The part of each set is plain text, in sections.

**Statistics** is the headline count: total patches applied, how many assets were patched, how many new assets were created, and how many errors occurred.

```
Statistics:
    Total Patches     42
    Patched Assets    37
    New Assets        1
    Errors            0
```

**Per-Pass Statistics** breaks the applied, skipped, and errored counts down by pass (Early, Default, Late), which is a quick way to see whether a pass you expected to do work actually did.

**All Errors** is where you look first when something threw. Each entry names the Lua file (for an error while loading a script) or the specific patch and asset (for an error inside a `Do` callback), followed by the error context:

```
All Errors:
    [Default] Parts / engine_2v_methalox_mainsail / BetterParts:RetuneMainsail
        ...exception details...
```

That line reads as: in the Default pass, while patching the `engine_2v_methalox_mainsail` asset under the Parts label, the patch `BetterParts:RetuneMainsail` threw. The id is [namespaced](/doc/dependencies-and-ordering-werp1yYh7P) so you can see exactly whose patch it was.

**Recognized Mod IDs** lists the mods PatchManager saw. If a mod you expected to depend on is missing here, that explains a `:Needs` that removed your patch.

**Removed Patches** lists patches that never ran because a constraint removed them, each with a status and context. A patch shows up here when its [dependencies](/doc/dependencies-and-ordering-werp1yYh7P) were not satisfied: a required mod or patch was absent, a conflict was present, or it was caught in an ordering cycle. A patch also shows here with the status `FEATURE` when the set does not allow it. The context gives the first feature that the patch did not have, for example `feature - BetterParts:HardMode`. For a `:NoFeature`, the context is `feature - not BetterParts:HardMode`. A patch from a mod that is off in the set shows with the default feature of that mod. If your patch is simply not happening and there is no error, this section is the next place to look.

**Per-label, per-asset breakdown** is the detailed log. For each label, each asset, and each pass, it lists every patch that touched that asset and its result:

```
Label - Parts:
    Asset - eva_kerbal:
        Pass - Early:
            BetterParts:KerbalImpactToleranceFix    APPLIED
```

The result is `APPLIED` when the patch ran, `REMOVED TARGET` when the patch deleted the asset by [returning "remove"](/doc/the-do-callback-Qq6LNtj9BT), a `SKIPPED` state when a [gate](/doc/gates-Zh2sLnyxZX) rejected the asset, along with the gate's message, or `ERRORED` when the patch callback errors.

## The summary's companion: the cache

The summary tells you what happened to each patch, but not what the asset ended up looking like. For that, look in the `pm_cache` folder that sits next to `pm_summary.log`. It contains the final patched JSON of each asset for each feature set, as the game loads it after all patches ran. When the summary says your patch `APPLIED` but the in-game result is still wrong, the cache is where you see the value your patch actually produced, and whether a later patch overwrote it. It is also the most reliable place to find the exact ids of other assets. See [Inspecting the cache](/doc/caching-and-invalidation-QifFi4oev9).

## A debugging routine

When a patch does not behave, work top down:


1. **Did it error?** Check **All Errors** for your patch's name. An exception there is the most direct answer.
2. **Did it get removed?** Check **Removed Patches**. A status here means that a dependency, a conflict or a feature stopped the patch. The cause is usually one of these:
   * A `:Needs`, `:Conflicts` or `:Feature` that you can fix.
   * A mod or feature that is off in the campaign that you tested.
3. **Did it get skipped?** Find your asset in the per-label breakdown. A skipped state with a message means a [gate](/doc/gates-Zh2sLnyxZX) rejected it, and the message tells you which one.
4. **Did it run but produce the wrong value?** It shows `APPLIED`, so the patch itself ran. Now the question is ordering: another patch in a later [pass or bucket](/doc/the-patch-lifecycle-bV7YhyoMv8) may have overwritten your change. Check which other patches touched the same asset and when.

Most "my patch is not working" problems are one of these four, and the summary distinguishes them at a glance.

## Logging from a patch

The summary tells you what happened to a patch, but not what your code saw while it ran. When you need that, log it. Every patch script has a `Log` global, the logger SpaceWarp provides, with one method per level:

```lua
Log:Info("starting up")
Log:Warning("something looks off")
Log:Error("this should not happen")
Log:Debug("part mass was " .. tostring(part.mass))
```

Use `Log` rather than Lua's `print`. Its output is attributed to your mod and tagged with a level, so you can find your own messages in a busy log and filter by severity. `print` is untagged and easy to lose.

Where a `Log` call runs matters, and it mirrors the [register-then-apply split](/doc/file-layout-and-discovery-vYcsLN5rtw):

* A `Log` call at the top level of your script runs once, during registration. Good for confirming a script loaded and for reporting setup decisions.
* A `Log` call inside a `Do` callback runs during patching, once per asset the patch actually touches. This is how you trace which assets a patch hit and what their values were, which is exactly the information the summary does not carry.

```lua
PM.Parts:Patch("InspectEngines")
        :Named("engine_*")
        :Do(function(part)
            Log:Debug("patching " .. part.partName .. ", mass " .. tostring(part.mass))
        end)
```

If you want a separately named logger to keep a subsystem's output distinct, request one from the SpaceWarp global, `SW:GetLogger("MyThing")`, and call the same `Info` / `Warning` / `Error` / `Debug` methods on it.