{"record":{"id":"132719c947fe15ff","repo":"babalae/better-genshin-impact","slug":"alias-132719","errorCode":null,"errorMessage":"未找到区域别名 {alias}","messagePattern":"未找到区域别名 (.+?)","errorType":"exception","errorClass":"KeyNotFoundException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs","lineNumber":339,"sourceCode":"        {\n            var resolved = ResolveRegionExpression(expression);\n            var value = EvaluateValue(resolved);\n            return value switch\n            {\n                Rect rect => rect,\n                _ => throw new InvalidOperationException($\"表达式 {expression} 未返回 Rect\")\n            };\n        }\n\n        private string ResolveRegionExpression(string expression)\n        {\n            var resolved = expression.Trim();\n            while (resolved.StartsWith('@'))\n            {\n                var alias = resolved[1..];\n                if (!_config.Regions.TryGetValue(alias, out resolved))\n                {\n                    throw new KeyNotFoundException($\"未找到区域别名 {alias}\");\n                }\n            }\n\n            return resolved;\n        }\n\n        private object EvaluateValue(string expression, string? skipVarName = null)\n        {\n            var normalizedExpression = NormalizeExpression(expression);\n            var ncalcExpression = new Expression(normalizedExpression);\n\n            foreach (var (name, value) in BuildParameters(skipVarName))\n            {\n                ncalcExpression.Parameters[name] = value;\n            }\n\n            ncalcExpression.Functions[\"rect\"] = args => BuildRect(args.Evaluate(0), args.Evaluate(1), args.Evaluate(2), args.Evaluate(3));\n            ncalcExpression.Functions[\"cutLeft\"] = args => _captureRect.CutLeft(ToDouble(args.Evaluate(0)));","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs#L321-L357","documentation":"A region (ROI) expression may start with '@' to reference a named alias from the JSON regions map. ResolveRegionExpression dereferences it and throws KeyNotFoundException when the alias is undefined, so the rectangle cannot be resolved.","triggerScenarios":"An object has \"roi\": \"@topBar\" but the Recognition.json defines no regions.topBar entry.","commonSituations":"Region alias removed/renamed but still referenced; typo in the alias; alias defined in a shared file not loaded.","solutions":["Declare the region alias in the regions map, e.g. \"regions\": { \"topBar\": \"rect(0,0,cw,40)\" }.","Inline the rect expression directly in roi if the alias is not needed.","Check alias spelling and case against the regions map keys."],"exampleFix":"// before\n// \"roi\": \"@topBar\"  with no regions.topBar -> throws\n\n// after\n// \"regions\": { \"topBar\": \"rect(0, 0, cw, 40)\" },\n// \"objects\": { \"x\": { \"roi\": \"@topBar\" } }","handlingStrategy":"validation","validationCode":"foreach (var (name, cfg) in config.Objects)\n{\n    if (cfg.Roi is { } r && r.TrimStart().StartsWith('@'))\n    {\n        var alias = r.Trim()[1..];\n        if (!config.Regions.ContainsKey(alias))\n            throw new InvalidOperationException($\"Object '{name}' references undefined region alias '@{alias}'.\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try { return RecognitionObjectJsonLoader.Load(config, objectName, context); }\ncatch (KeyNotFoundException ex) when (ex.Message.Contains(\"未找到区域别名\"))\n{ Logger.LogError(ex, \"Undefined region alias referenced.\"); throw; }","preventionTips":["Keep the regions map and '@' ROI references consistent.","Lint all '@'-prefixed references (templates and regions) during CI.","Inline rect expressions for one-off regions to avoid alias drift."],"tags":["config","region","alias","key-not-found"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}