babalae/better-genshin-impact · error · Exception
Failed to deserialize macro
Error message
Failed to deserialize macro
What it means
Thrown by KeyMouseMacroPlayer.PlayMacro at line 31 when JsonSerializer.Deserialize<KeyMouseScript>(macro, KeyMouseRecorder.JsonOptions) yields null. Note the `?? throw` only fires when deserialization succeeds but returns a null reference (input JSON is the literal "null"); malformed or empty JSON throws JsonException BEFORE reaching this line. KeyMouseRecorder.JsonOptions uses camelCase naming, allows comments and trailing commas, so structurally-permissive but schema-mismatched input still deserializes to a default/null object rather than throwing.
Source
Thrown at BetterGenshinImpact/Core/Recorder/KeyMouseMacroPlayer.cs:31
using System.Threading.Tasks;
using System.Windows.Forms;
using Fischless.WindowsInput;
using Vanara.PInvoke;
using Wpf.Ui.Violeta.Controls;
namespace BetterGenshinImpact.Core.Recorder;
public class KeyMouseMacroPlayer
{
public static async Task PlayMacro(string macro, CancellationToken ct, bool withDelay = true)
{
if (!TaskContext.Instance().IsInitialized)
{
Toast.Warning("请先在启动页,启动截图器再使用本功能");
return;
}
var script = JsonSerializer.Deserialize<KeyMouseScript>(macro, KeyMouseRecorder.JsonOptions) ?? throw new Exception("Failed to deserialize macro");
script.Adapt(TaskContext.Instance().SystemInfo.CaptureAreaRect, TaskContext.Instance().DpiScale);
SystemControl.ActivateWindow();
if (withDelay)
{
for (var i = 3; i >= 1; i--)
{
TaskControl.Logger.LogInformation("{Sec}秒后进行重放...", i);
await Task.Delay(1000, ct);
}
TaskControl.Logger.LogInformation("开始重放");
}
await PlayMacro(script.MacroEvents, ct);
}
public static async Task PlayMacro(List<MacroEvent> macroEvents, CancellationToken ct)View on GitHub (pinned to a7cb36712d)
Solutions
- Validate the macro string before calling PlayMacro: reject null, empty, whitespace, and the literal "null".
- Catch JsonException separately around the Deserialize call to surface real parse errors with line/byte position.
- If the macro file is corrupt, re-record it with the built-in KeyMouseRecorder and overwrite the file.
- Log the file path and first 200 chars of the macro string when this fires to identify which file is bad.
Example fix
// before
var script = JsonSerializer.Deserialize<KeyMouseScript>(macro, KeyMouseRecorder.JsonOptions)
?? throw new Exception("Failed to deserialize macro");
// after
if (string.IsNullOrWhiteSpace(macro) || macro.Trim() == "null")
{
throw new InvalidOperationException("Macro content is empty or null; the macro file may be corrupt. Re-record it.");
}
KeyMouseScript script;
try
{
script = JsonSerializer.Deserialize<KeyMouseScript>(macro, KeyMouseRecorder.JsonOptions)
?? throw new InvalidOperationException("Failed to deserialize macro: result was null. File may be corrupt or schema-mismatched.");
}
catch (JsonException ex)
{
throw new InvalidOperationException($"Failed to parse macro JSON at {ex.Path}: {ex.Message}", ex);
} Defensive patterns
Strategy: validation
Validate before calling
// C# caller guard before PlayMacro
if (string.IsNullOrWhiteSpace(macro) || macro.Trim() == "null")
{
throw new InvalidOperationException("Macro content is empty/null; the macro file may be corrupt. Re-record it.");
} Try / catch
try
{
var script = JsonSerializer.Deserialize<KeyMouseScript>(macro, KeyMouseRecorder.JsonOptions);
if (script is null) throw new InvalidOperationException("Macro deserialized to null; file may be corrupt.");
}
catch (JsonException ex)
{
// Surface the real parse error (path/position) instead of the generic message
logger.LogError(ex, "Macro JSON parse failed at {Path}", ex.Path);
throw;
} Prevention
- Validate macro files after writing by reading them back and deserializing once before storing.
- Treat the literal JSON string "null" as a corrupt-file signal and prompt re-record.
- Catch JsonException separately so a parse error is not misreported as 'deserialized to null'.
- Wrap file reads in a sanity check: non-empty, starts with '{', parseable.
When it happens
Trigger: Calling PlayMacro(macro, ct) where `macro` is the string "null", or where a recorded macro file is empty/contains only "null". Passing a non-KeyMouseScript-shaped JSON object whose root deserializes to null. Reading a corrupt or truncated .json macro file whose saved content became "null".
Common situations: A macro .json file was corrupted by an interrupted write (power loss, crash mid-save), leaving it empty or containing "null". The user hand-edited the JSON and removed the macroEvents/info fields. A schema/version change in KeyMouseScript made old files deserialize to null. Passing the wrong file's contents (e.g. a config file) into PlayMacro.
Related errors
- 无法解析 RecognitionObject 配置文件: {filePath}
- 解析配置组JSON配置失败
- Failed to deserialize JSON.
- JSON 战斗策略格式错误:{ex.Message}
- config.json 解析失败
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/ebdc788f4755d7df.
Report an issue: GitHub.