babalae/better-genshin-impact · error · InvalidOperationException
变量 {name} 存在循环引用
Error message
变量 {name} 存在循环引用 What it means
ResolveVariable uses a _resolvingVars HashSet to track the in-progress resolution chain. If adding the current name fails, a cycle is detected (var A depends on var B which depends back on var A), and InvalidOperationException is thrown to prevent infinite recursion.
Source
Thrown at BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs:415
return parameters;
}
private double ResolveVariable(string name)
{
if (_resolvedVars.TryGetValue(name, out var resolvedValue))
{
return resolvedValue;
}
if (!_config.Vars.TryGetValue(name, out var expression))
{
throw new KeyNotFoundException($"未找到变量 {name}");
}
if (!_resolvingVars.Add(name))
{
throw new InvalidOperationException($"变量 {name} 存在循环引用");
}
try
{
var value = ToDouble(EvaluateValue(expression, name));
_resolvedVars[name] = value;
return value;
}
finally
{
_resolvingVars.Remove(name);
}
}
private string NormalizeExpression(string expression)
{
var normalized = expression;
var parameterNames = GetParameterNames()View on GitHub (pinned to a7cb36712d)
Solutions
- Break the cycle by making at least one variable independent (a constant or expression of builtins only).
- Re-express one var in terms of cw/ch/cx/cy/s rather than another var.
- Run a cycle check over the vars graph during config validation.
Example fix
// before
// "vars": { "a": "b + 1", "b": "a + 1" } -> cycle -> throws
// after
// "vars": { "a": "b + 1", "b": "cw * 0.1" } Defensive patterns
Strategy: validation
Validate before calling
static void AssertNoVarCycles(RecognitionObjectJsonFile config)
{
var deps = config.Vars.ToDictionary(
kv => kv.Key,
kv => System.Text.RegularExpressions.Regex.Matches(kv.Value, "[A-Za-z_][A-Za-z0-9_]*")
.Select(m => m.Value).Where(v => config.Vars.ContainsKey(v)).ToHashSet());
var seen = new HashSet<string>();
bool Dfs(string n, HashSet<string> stack)
{
if (stack.Contains(n)) return true;
if (!seen.Add(n)) return false;
stack.Add(n);
foreach (var d in deps[n]) if (Dfs(d, stack)) return true;
stack.Remove(n);
return false;
}
foreach (var n in config.Vars.Keys)
if (Dfs(n, new())) throw new InvalidOperationException($"Cycle detected in vars involving '{n}'.");
} Try / catch
try { return RecognitionObjectJsonLoader.Load(config, objectName, context); }
catch (InvalidOperationException ex) when (ex.Message.Contains("循环引用"))
{ Logger.LogError(ex, "Circular var reference in Recognition.json."); throw; } Prevention
- Express each var in terms of constants or builtins; avoid var-to-var chains.
- Run a cycle check over the vars graph during config validation/CI.
- Review var edits that introduce new cross-references.
When it happens
Trigger: vars declares mutually referencing variables, e.g. { "a": "b + 1", "b": "a + 1" }, or a self-reference like { "a": "a + 1" }.
Common situations: Two vars accidentally reference each other; a var self-references during a refactor; copy-paste of an expression that points back at itself.
Related errors
- 表达式 {expression} 未返回 Rect
- 未找到变量 {name}
- 未找到名称为 {objectName} 的 RecognitionObject 配置
- 对象 {objectName} 缺少 template 配置
- {fieldName} 必须是 1 到 4 个数字
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/5eb516507364a6c2.
Report an issue: GitHub.