# Troubleshooting ## First stop: the log Everything is in `%APPDATA%\LiveWall\logs\livewall-YYYYMMDD.log`. Plugin lines are prefixed with the plugin id: ``` [com.example.clock] Clock plugin starting (plugin API 1.0, host 1.8.0) [plugins] loaded com.example.clock v1.0.0 (sha256 3f8c…, verified) ``` Also useful: * **Plugins ▸ Plugin log** — in-app summary: every plugin, its state, hash, permissions, overlays, pages, commands, filters, renderers. * **Advanced ▸ Diagnostics** — the same report inside the full diagnostics dump, plus the engine state. * **Advanced ▸ Open log folder**. ## The plugin does not appear in the list | Symptom | Cause | Fix | |---|---|---| | Folder listed but named after the folder | `plugin.json` missing or unparsable | Fix the JSON; the row says `Invalid manifest: …` | | Nothing at all | Wrong folder | Must be `%APPDATA%\LiveWall\plugins\\plugin.json`, not `plugins\plugin.json` | | Nothing at all | Plugin system off | **Plugins ▸ Enable the plugin system** (warning required) | | Appears, greyed state `Incompatible` | `apiVersion` major mismatch or `minHostVersion` too new | Update the plugin, or lower `minHostVersion` | | Appears, `Rejected` | `checksum` in the manifest does not match the DLL | Rebuild, or clear `checksum` | | Appears, `Failed` | Assembly/type problem, or `Initialize` threw | Read the state message; fix the type name or the exception | | Appears, `NotApproved` | Loaded and ready, waiting for the user | Press **Enable** and accept the warning | ## `Enable` does nothing / warning reappears every time * **"allow unverified plugins" is off** and the plugin is unverified → turn that option on (in the *Plugin system* card) or use a build whose hash you approved before. * The hash changes on every build (normal). Approving a build approves *that* binary; rebuild and you are asked again. During development, leave **Allow unverified** on and keep an eye on the log rather than re-approving each time. * A **Forget trust** click clears the stored hash — that is what it does. ## "Could not load file or assembly … LiveWall.Sdk" The plugin was built with an *incompatible* SDK, or it shipped its own `LiveWall.Sdk.dll`. Delete the copy from the plugin folder and reference the SDK with `false`. ## "Cannot cast … to ILiveWallPlugin" Same cause: a second copy of the contract assembly. The plugin's `ILiveWallPlugin` came from a different assembly identity than the host's. ## Overlay does not show up 1. Is the plugin **Active** and does the log mention `overlay registered`? 2. Is the desktop icon window alive? LiveWall creates the overlay host window even with desktop icons disabled, but a third-party shell replacement (StartAllBack, ExplorerPatcher) can break WorkerW — press **Re-attach** on the Display tab. 3. Did you return a `FrameworkElement` with a size? A `StackPanel` with no children is invisible. 4. Is it *behind* the icons by design? The overlay sits above the wallpaper and below the icons; text in the top-right corner is a safe place to test. 5. Did you call `OnVisibilityChanged` correctly? LiveWall calls it with `false` when overlays are hidden (tray **Hide overlay**), so a timer you stopped there must be restarted on `true`. ## Clicks on my overlay do nothing Expected. The overlay layer is `IsHitTestVisible = false`: clicks must reach the desktop icons. If you need interaction, that is a *renderer* feature (renderers live in the wallpaper window and can be made interactive with `InteractiveMode`), not an overlay feature. ## Settings page is blank `CreateView` threw. The exception is shown in the page *and* logged. The usual culprit is referencing `LiveWall.Themes` resources by key that does not exist — the safe keys are `BgWindow`, `BgCard`, `BgField`, `BgHover`, `BorderBrushSoft`, `TextBrush`, `TextDim`, `AccentBrush`, `AccentSoft`, `GreenBrush`, `DangerBrush`, and the styles `Card`, `Hint`, `SectionTitle`, `PageTitle`, `AccentButton`, `GhostButton`, `TinyButton`, `Label`, `Mono`. ## Hotkey does nothing * Another app (or LiveWall itself) already owns the combination — the log says so. * Gesture syntax: modifiers first (`Ctrl+Alt+K`), one key. `Ctrl+Shift+3` is not valid, `Ctrl+Shift+D3` is. * The `Hotkeys` permission must be declared. ## Filter breaks wallpaper changes Filters run **before** the engine applies a request, including requests from playlists and other plugins. A filter that always returns a fixed request effectively pins the wallpaper (that is the point of the sample's *Pin wallpaper* option). Exceptions inside `Apply` disable your filter for that pass and are logged; they do not disable the plugin. ## Renderer never gets used * `CanRender` must return `true` for the request the engine actually sees — after filters. Log what you receive. * Another plugin with a higher `Priority` claimed it first. Priorities are per plugin; the first `true` wins. * The `Renderer` permission must be declared, otherwise `AddRenderer` is refused. * After a source change LiveWall calls `Create` once and `Load` per source. If `Load` throws, the message appears in the status line and the plugin is not retried for that source. ## Unloading LiveWall unloads a plugin when it is disabled, rescanned, or when the app exits. The collectible load context only actually releases the assembly if nothing keeps a reference alive: * unsubscribe every `IDisposable` you got from `Events.Subscribe` in `Shutdown`; * stop and unhook `DispatcherTimer`s, `System.Timers.Timer`s, `FileSystemWatcher`s; * do not keep static references **in the host's types** to your objects (a static in a host-owned class is fine only if it lives in your assembly); * do not leave `Task`s running: observe `context.ShutdownToken`. If a plugin stays "loaded" after Disable, the log says `unload deferred` — restart LiveWall to finish the job. This is a leak in the plugin, not in LiveWall. ## Reporting a bug Include: LiveWall version, plugin id + version + hash (from the warning dialog or **Plugin log**), the relevant log excerpt, and the exact steps. If the app crashed, the last lines of the log before the crash are usually enough to identify the plugin.