babalae/better-genshin-impact · error · KeyNotFoundException

未找到模板别名 {alias}

Error message

未找到模板别名 {alias}

What it means

A template value may start with '@' to reference a named alias defined in the JSON templates map. ResolveTemplate dereferences the alias and throws KeyNotFoundException when the alias is not declared, so the template chain cannot resolve to a real file.

Source

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

            return string.IsNullOrWhiteSpace(templateMode)
                ? ImreadModes.Color
                : ParseEnumExact<ImreadModes>(templateMode, nameof(templateMode));
        }

        private string ResolveTemplate(string? template, string objectName)
        {
            if (string.IsNullOrWhiteSpace(template))
            {
                throw new InvalidOperationException($"对象 {objectName} 缺少 template 配置");
            }

            var resolved = template.Trim();
            while (resolved.StartsWith('@'))
            {
                var alias = resolved[1..];
                if (!_config.Templates.TryGetValue(alias, out resolved))
                {
                    throw new KeyNotFoundException($"未找到模板别名 {alias}");
                }
            }

            return resolved;
        }

        private Rect EvaluateRect(string expression)
        {
            var resolved = ResolveRegionExpression(expression);
            var value = EvaluateValue(resolved);
            return value switch
            {
                Rect rect => rect,
                _ => throw new InvalidOperationException($"表达式 {expression} 未返回 Rect")
            };
        }

        private string ResolveRegionExpression(string expression)

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Declare the alias in the templates map, e.g. "templates": { "sharedBtn": "btn.png" }.
  2. Replace the @alias reference with a direct filename if the alias is not needed.
  3. Check alias spelling and case against the templates map keys.

Example fix

// before
// "template": "@sharedBtn"  with no templates.sharedBtn -> throws

// after
// "templates": { "sharedBtn": "btn_start.png" },
// "objects": { "x": { "type": "TemplateMatch", "template": "@sharedBtn" } }
Defensive patterns

Strategy: validation

Validate before calling

foreach (var (name, cfg) in config.Objects)
{
    if (cfg.Template is { } t && t.TrimStart().StartsWith('@'))
    {
        var alias = t.Trim()[1..];
        if (!config.Templates.ContainsKey(alias))
            throw new InvalidOperationException($"Object '{name}' references undefined template alias '@{alias}'.");
    }
}

Try / catch

try { return RecognitionObjectJsonLoader.Load(config, objectName, context); }
catch (KeyNotFoundException ex) when (ex.Message.Contains("未找到模板别名"))
{ Logger.LogError(ex, "Undefined template alias referenced."); throw; }

Prevention

When it happens

Trigger: An object has "template": "@sharedBtn" but the Recognition.json defines no templates.sharedBtn entry.

Common situations: Alias renamed or deleted but still referenced; typo in the alias name; alias defined in a different file that was not merged.

Related errors


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