babalae/better-genshin-impact · error · InvalidOperationException
表达式 {expression} 未返回 Rect
Error message
表达式 {expression} 未返回 Rect What it means
EvaluateRect runs the ROI expression through NCalc and expects a Rect result (produced by the rect()/cutXxx() helper functions). If the expression evaluates to a scalar number or any non-Rect value, it throws InvalidOperationException, because a region of interest must be a rectangle.
Source
Thrown at BetterGenshinImpact/Core/Recognition/RecognitionObjectJsonLoader.cs:327
{
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)
{
var resolved = expression.Trim();
while (resolved.StartsWith('@'))
{
var alias = resolved[1..];
if (!_config.Regions.TryGetValue(alias, out resolved))
{
throw new KeyNotFoundException($"未找到区域别名 {alias}");
}
}
return resolved;
}
View on GitHub (pinned to a7cb36712d)
Solutions
- Wrap the expression in rect(x, y, width, height), e.g. "rect(0, 0, cw * 0.5, ch)".
- Use a cutXxx(...) helper or a region alias that resolves to a Rect-producing expression.
- Confirm the expression returns a Rect by testing it before deployment.
Example fix
// before (Recognition.json) // "roi": "cw * 0.5" -> evaluates to a number -> throws // after // "roi": "rect(0, 0, cw * 0.5, ch)"
Defensive patterns
Strategy: validation
Validate before calling
// Evaluate the ROI expression in a dry-run and assert the result type
using NCalc.Expression e = new(expr);
// supply cw/ch/cx/cy/s parameters as in the loader
var result = e.Evaluate();
if (result is not OpenCvSharp.Rect)
throw new InvalidOperationException($"ROI expression '{expr}' must return a Rect (use rect(...)/cutXxx(...))."); Type guard
static bool IsRectExpression(string expression, IDictionary<string, object> parameters)
{
try
{
var e = new NCalc.Expression(expression);
foreach (var (k, v) in parameters) e.Parameters[k] = v;
return e.Evaluate() is OpenCvSharp.Rect;
}
catch { return false; }
} Try / catch
try { return RecognitionObjectJsonLoader.Load(config, objectName, context); }
catch (InvalidOperationException ex) when (ex.Message.Contains("未返回 Rect"))
{ Logger.LogError(ex, "ROI expression did not evaluate to a Rect."); throw; } Prevention
- Always wrap ROI dimensions in rect(...) or a cutXxx(...) helper.
- Distinguish ROI (needs Rect) from numeric thresholds in authoring tooling.
- Unit-test ROI expressions against sample capture sizes.
When it happens
Trigger: A RecognitionObject has "roi": "cw * 0.5" (a bare number) instead of "roi": "rect(0, 0, cw, ch)" or a cutXxx(...) call.
Common situations: ROI confused with a numeric threshold; forgot to wrap dimensions in rect(); referenced a region alias that resolves to a number.
Related errors
- 变量 {name} 存在循环引用
- 未找到名称为 {objectName} 的 RecognitionObject 配置
- 对象 {objectName} 缺少 template 配置
- 未找到变量 {name}
- {fieldName} 必须是 1 到 4 个数字
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/8ace738f92a9889e.
Report an issue: GitHub.