{"record":{"id":"100063a876a87514","repo":"babalae/better-genshin-impact","slug":"recognitionobject-filepath","errorCode":null,"errorMessage":"无法解析 RecognitionObject 配置文件: {filePath}","messagePattern":"无法解析 RecognitionObject 配置文件: (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs","lineNumber":44,"sourceCode":"}\n\npublic static class RecognitionObjectJsonLoader\n{\n    private sealed class LoggerTag;\n\n    private static readonly ILogger Logger = App.GetLogger<LoggerTag>();\n\n    public static RecognitionObject LoadFromFile(string filePath, string objectName, RecognitionObjectJsonLoadContext context)\n    {\n        ArgumentNullException.ThrowIfNull(filePath);\n        ArgumentNullException.ThrowIfNull(objectName);\n        ArgumentNullException.ThrowIfNull(context);\n\n        try\n        {\n            var json = File.ReadAllText(filePath, Encoding.UTF8);\n            var config = JsonConvert.DeserializeObject<RecognitionObjectJsonFile>(json)\n                         ?? throw new InvalidOperationException($\"无法解析 RecognitionObject 配置文件: {filePath}\");\n\n            return Load(config, objectName, context);\n        }\n        catch (Exception ex)\n        {\n            Logger.LogError(ex,\n                \"Recognition 加载失败: {ObjectName} @ {CaptureWidth}x{CaptureHeight}, file={FilePath}\",\n                objectName,\n                context.CaptureWidth,\n                context.CaptureHeight,\n                filePath);\n            throw;\n        }\n    }\n\n    public static RecognitionObject Load(RecognitionObjectJsonFile config, string objectName, RecognitionObjectJsonLoadContext context)\n    {\n        ArgumentNullException.ThrowIfNull(config);","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs#L26-L62","documentation":"RecognitionObjectJsonLoader.LoadFromFile reads the JSON and deserializes it into a RecognitionObjectJsonFile. If the deserialized result is null (empty file, a literal null, or content that does not map to the expected object shape), it throws InvalidOperationException with the file path. Malformed JSON instead throws a Newtonsoft.Json reader exception earlier; this specific throw is for a successfully parsed but null result.","triggerScenarios":"Calling LoadFromFile where Recognition.json is empty, contains the literal null, or is a JSON array/scalar rather than the expected object with objects/templates/vars fields.","commonSituations":"File truncated to zero bytes by a bad save or merge conflict; file overwritten with an array; encoding BOM causing a parse edge case; hand-edited file that became invalid.","solutions":["Restore a valid Recognition.json containing an object with at least an empty \"objects\" map.","Check the file is not empty and that its root is a JSON object, not an array or scalar.","Run the JSON through a validator/linter before deploying.","Ensure merge conflicts are fully resolved (no leftover conflict markers)."],"exampleFix":"// before\nvar ro = RecognitionObjectJsonLoader.LoadFromFile(path, name, ctx); // file is empty/null\n\n// after\nvar raw = File.ReadAllText(path, Encoding.UTF8);\nif (string.IsNullOrWhiteSpace(raw))\n    throw new InvalidOperationException($\"Recognition.json is empty: {path}\");\nvar ro = RecognitionObjectJsonLoader.LoadFromFile(path, name, ctx);","handlingStrategy":"validation","validationCode":"static bool IsValidRecognitionJson(string path)\n{\n    if (!File.Exists(path)) return false;\n    var raw = File.ReadAllText(path, Encoding.UTF8);\n    if (string.IsNullOrWhiteSpace(raw)) return false;\n    try { return JsonConvert.DeserializeObject<RecognitionObjectJsonFile>(raw) is not null; }\n    catch { return false; }\n}\n\nif (!IsValidRecognitionJson(filePath))\n    throw new InvalidOperationException($\"Recognition config invalid or null: {filePath}\");","typeGuard":null,"tryCatchPattern":"try { return RecognitionObjectJsonLoader.LoadFromFile(filePath, objectName, context); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"无法解析 RecognitionObject 配置文件\"))\n{ Logger.LogError(ex, \"Recognition.json parsed to null: {Path}\", filePath); throw; }","preventionTips":["Never commit an empty or null Recognition.json.","Run a JSON schema validation pass on Recognition.json during CI.","Resolve merge conflicts fully so the file stays a valid object."],"tags":["config","json","deserialization","recognition"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}