{"record":{"id":"71e84aba2a43826a","repo":"babalae/better-genshin-impact","slug":"name","errorCode":null,"errorMessage":"未找到变量 {name}","messagePattern":"未找到变量 \\{name\\}","errorType":"exception","errorClass":"KeyNotFoundException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs","lineNumber":410,"sourceCode":"                    continue;\n                }\n\n                parameters[varName] = ResolveVariable(varName);\n            }\n\n            return parameters;\n        }\n\n        private double ResolveVariable(string name)\n        {\n            if (_resolvedVars.TryGetValue(name, out var resolvedValue))\n            {\n                return resolvedValue;\n            }\n\n            if (!_config.Vars.TryGetValue(name, out var expression))\n            {\n                throw new KeyNotFoundException($\"未找到变量 {name}\");\n            }\n\n            if (!_resolvingVars.Add(name))\n            {\n                throw new InvalidOperationException($\"变量 {name} 存在循环引用\");\n            }\n\n            try\n            {\n                var value = ToDouble(EvaluateValue(expression, name));\n                _resolvedVars[name] = value;\n                return value;\n            }\n            finally\n            {\n                _resolvingVars.Remove(name);\n            }\n        }","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs#L392-L428","documentation":"ResolveVariable throws KeyNotFoundException when a variable name is not present in the config.Vars map. Under normal flow BuildParameters only iterates declared vars, so this is a defensive guard against a variable referenced through the expression machinery that is not declared in the vars map.","triggerScenarios":"A var's expression references a name that survives NormalizeExpression but is absent from vars and from the builtins (cw/ch/cx/cy/s), e.g. after renaming a var and leaving a dangling reference inside another var's expression.","commonSituations":"Renamed a var in vars but forgot to update a var expression that referenced it; merged configs where a referenced var was removed.","solutions":["Declare the missing variable in the vars map.","Remove the dangling reference from the referencing var's expression.","Use a builtin (cw, ch, cx, cy, s) instead of an undeclared name."],"exampleFix":"// before\n// \"vars\": { \"a\": \"b + 1\" }   // b is not declared -> ResolveVariable('b') throws\n\n// after\n// \"vars\": { \"a\": \"b + 1\", \"b\": \"10\" }","handlingStrategy":"validation","validationCode":"var builtins = new HashSet<string>(StringComparer.Ordinal) { \"cw\", \"ch\", \"cx\", \"cy\", \"s\" };\nforeach (var (name, expr) in config.Vars)\n{\n    // crude token check: any identifier not a builtin/function/number must be in vars\n    foreach (var token in System.Text.RegularExpressions.Regex.Matches(expr, \"[A-Za-z_][A-Za-z0-9_]*\"))\n    {\n        var id = token.ToString()!;\n        if (!builtins.Contains(id) && !config.Vars.ContainsKey(id)\n            && !new[]{\"rect\",\"cutLeft\",\"cutRight\",\"cutTop\",\"cutBottom\",\"cutLeftTop\",\"cutRightTop\",\"cutLeftBottom\",\"cutRightBottom\"}.Contains(id))\n            throw new InvalidOperationException($\"Var '{name}' references undeclared variable '{id}'.\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try { return RecognitionObjectJsonLoader.Load(config, objectName, context); }\ncatch (KeyNotFoundException ex) when (ex.Message.Contains(\"未找到变量\"))\n{ Logger.LogError(ex, \"Undeclared variable referenced by a var expression.\"); throw; }","preventionTips":["When renaming a var, grep all var expressions for the old name.","Prefer builtins (cw/ch/cx/cy/s) over user vars where possible.","Run a var-dependency lint during CI."],"tags":["config","vars","ncalc","key-not-found"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}