# Gum Tool Errors

> Gum Tool Error System Reference

- Skill: `vchelaru/gum-tool-errors` (Agent Skill)
- Install (CLI): `npx skillmds@latest add vchelaru/gum-tool-errors`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vchelaru/gum-tool-errors/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: vchelaru (https://skillmd.com/u/vchelaru)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/vchelaru/gum-tool-errors

---


# Gum Tool Error System Reference

## Architecture

Two tiers of error detection, merged into one display.

**Tier 1 — Core checks** (`ErrorChecker`): Runs on a given `ElementSave`. Called by both the tree view (icon refresh) and the Errors tab (list refresh).

**Tier 2 — Plugin checks**: Plugins implement `GetAllErrors` event (declared on `PluginBase`) and return `IEnumerable<ErrorViewModel>`. Called via `PluginManager.FillWithErrors()`, which is invoked at the end of `ErrorChecker.GetErrorsFor()`.

## Error Pipeline

```
User action (e.g. InstanceAdd, VariableSet, Undo)
    ↓
MainTreeViewPlugin → RefreshErrorIndicatorsForElement(element)
    ↓
ErrorChecker.GetErrorsFor(element, project)
    ↓
ElementTreeViewManager.UpdateErrorIndicatorsForElement()
    └─ Swaps icon to ExclamationIndex (6) if errors exist

SEPARATELY — Errors tab:
MainErrorsPlugin → UpdateErrorsForElement() or HandleErrorRefreshRequest()
    ↓
ErrorChecker.GetErrorsFor(element, project)
    ↓
AllErrorsViewModel.Errors (ObservableCollection) → ErrorDisplay.xaml ListBox
```

The tree icon refresh and the Errors tab refresh are independent. Both call `ErrorChecker.GetErrorsFor` but are triggered separately.

## Adding New Error Checks

**Core check** (missing references, structural problems): Add it to `HeadlessErrorChecker.GetErrorsForInternal` in `Gum.ProjectServices`, **not** the tool's `Gum/Managers/ErrorChecker.cs`. The tool's checker delegates to the headless one (and converts `ErrorResult` → `ErrorViewModel`); putting checks in the headless layer means both the tool's Errors tab (per-selected-element refresh) and `gumcli check` (whole-project pass via `GetAllErrors`) surface them automatically. Pattern: iterate states/instances, emit `new ErrorResult { ElementName = ..., Message = ..., Code = "GUM00XX", Severity = ... }`. Register the code in `ErrorDocsRegistry` to get a help URL.

**Plugin check** (feature-specific, tool-side only): Subscribe to `GetAllErrors` in your plugin's `StartUp()`, return `IEnumerable<ErrorViewModel>`, and set `item.OwnerPlugin = this` on each. Plugin checks only show in the tool — the CLI doesn't load plugins. If the check should fire in CI / pre-commit, use the headless path above instead.

**Fixable errors**: set `ActionName` and `ActionCommand` on the `ErrorViewModel` to render a button beside the row that resolves the error in place (`HasAction` drives its visibility). An action that destroys anything unrecoverable still owes the user a confirmation before it runs.

**Triggering refresh**: Send `RequestErrorRefreshMessage` via messenger to refresh the Errors tab list. Tree icon refresh is driven by existing plugin event subscriptions in `MainTreeViewPlugin`.

## Current Core Checks (ErrorChecker)

| Method | What it detects |
|--------|----------------|
| `GetBehaviorErrorsFor` | Missing behavior references; missing/wrong-type required instances and variables |
| `GetMissingElementBaseTypeErrorFor` | Element's own base type points to a deleted/nonexistent element |
| `GetMissingBaseTypeErrorsFor` | Instance's base type points to a nonexistent element |
| `GetParentErrorsFor` | Parent variable references a nonexistent instance |
| `GetInvalidVariableTypeErrorsFor` | Custom variable uses an unknown or misnamed type (State suffix issues) |
| `GetMissingSourceFileErrorsFor` | GUM0004: element file missing on disk; GUM0008 when it exists under a different case |
| `GetMissingExternalFileErrorsFor` | GUM0006: referenced texture/font file missing (via `GumProjectDependencyWalker`); GUM0008 for a case-only difference |

## Key Files

| File | Purpose |
|------|---------|
| `Gum/Managers/ErrorChecker.cs` | All core error checks |
| `Tools/Gum.Presentation/Managers/ErrorViewModel.cs` | Data model (`Message`, `OwnerPlugin` — `object?`, headless `Gum.Presentation`, ADR-0005) |
| `Gum/Managers/IErrorChecker.cs` | Interface |
| `Gum/Plugins/InternalPlugins/Errors/MainErrorsPlugin.cs` | Errors tab plugin; handles `RequestErrorRefreshMessage` |
| `Tools/Gum.Presentation/Plugins/InternalPlugins/Errors/AllErrorsViewModel.cs` | ObservableCollection of errors; `CountDescription` for tab header (headless `Gum.Presentation`, ADR-0005) |
| `Gum/Plugins/InternalPlugins/TreeView/ElementTreeViewManager.cs` | `UpdateErrorIndicatorsForElement`; `ExclamationIndex = 6` |
| `Gum/Messages/RequestErrorRefreshMessage.cs` | Message to force Errors tab refresh |
| `Tool/Tests/GumToolUnitTests/Managers/ErrorCheckerTests.cs` | Unit tests for ErrorChecker |

## Element Reload and Errors

When an element file changes on disk, `FileChangeReactionLogic.ReactToElementSaveChanged` calls `_pluginManager.ElementReloaded(element)`. `MainErrorsPlugin` subscribes to `ElementReloaded` and calls `UpdateErrorsForElement` — this is the correct trigger for refreshing errors after a reload.

Do **not** rely on `ElementSelected` alone for error refresh after reload: the reload path temporarily sets `SelectedElement = null` (to force a UI reset), which clears errors, and the subsequent re-selection uses `file.StandardizedNoPathNoExtension` which fails to find elements in subfolders — so errors would never be repopulated.

## Non-Obvious Behaviors

**Two separate refreshes**: The "!" icon in the tree and the Errors tab list are populated independently. Changing `ErrorChecker` automatically affects both, but only if the right events trigger both refresh paths.

**Cache wrapping**: `ErrorChecker.GetErrorsFor` wraps its checks in `ObjectFinder.Self.EnableCache()` / `DisableCache()`. New checks added inside the method benefit from this automatically.

**`IsSourceFileMissing` is separate**: The tree view shows "!" if `element.IsSourceFileMissing || hasErrors`. Source file missing is not surfaced as an `ErrorViewModel` — it's a flag on the element itself, checked directly by `UpdateErrorIndicatorsForElement`.

