babalae/better-genshin-impact · error · KeyNotFoundException

未找到变量

Error message

未找到变量 {name}

What it means

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.

Solutions

  1. Declare the missing variable in the vars map.
  2. Remove the dangling reference from the referencing var's expression.
  3. Use a builtin (cw, ch, cx, cy, s) instead of an undeclared name.

Example fix

// before
// "vars": { "a": "b + 1" }   // b is not declared -> ResolveVariable('b') throws

// after
// "vars": { "a": "b + 1", "b": "10" }
Defensive patterns

Strategy: validation

Validate before calling

var builtins = new HashSet<string>(StringComparer.Ordinal) { "cw", "ch", "cx", "cy", "s" };
foreach (var (name, expr) in config.Vars)
{
    // crude token check: any identifier not a builtin/function/number must be in vars
    foreach (var token in System.Text.RegularExpressions.Regex.Matches(expr, "[A-Za-z_][A-Za-z0-9_]*"))
    {
        var id = token.ToString()!;
        if (!builtins.Contains(id) && !config.Vars.ContainsKey(id)
            && !new[]{"rect","cutLeft","cutRight","cutTop","cutBottom","cutLeftTop","cutRightTop","cutLeftBottom","cutRightBottom"}.Contains(id))
            throw new InvalidOperationException($"Var '{name}' references undeclared variable '{id}'.");
    }
}

Try / catch

try { return RecognitionObjectJsonLoader.Load(config, objectName, context); }
catch (KeyNotFoundException ex) when (ex.Message.Contains("未找到变量"))
{ Logger.LogError(ex, "Undeclared variable referenced by a var expression."); throw; }

Prevention

When it happens

Trigger: 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.

Common situations: Renamed a var in vars but forgot to update a var expression that referenced it; merged configs where a referenced var was removed.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/71e84aba2a43826a. Report an issue: GitHub.

Appendix: source

Thrown at BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs:410

                    continue;
                }

                parameters[varName] = ResolveVariable(varName);
            }

            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);
            }
        }

View on GitHub (pinned to a7cb36712d)