babalae/better-genshin-impact · error · InvalidOperationException

无法从 {fieldName} OCR 结果中解析等级:{text}

Error message

无法从 {fieldName} OCR 结果中解析等级:{text}

What it means

`ParseLevelPair` is the throwing variant of `TryParseLevelPair`: it requires at least two digit-runs in the OCR text and both to be > 0. If the level text doesn't contain two positive integers (e.g. '/90', 'Lv', or garbage), parsing is impossible and it throws with the offending text.

Source

Thrown at BetterGenshinImpact/GameTask/CharacterDevelopment/CharacterDevelopmentTask.cs:1162

                break;
            case SkillTalentType:
                result.SkillLevel = level;
                result.SkillHasBonus = hasBonus;
                break;
            case BurstTalentType:
                result.BurstLevel = level;
                result.BurstHasBonus = hasBonus;
                break;
            default:
                throw new InvalidOperationException($"未知天赋类型:{type}");
        }
    }

    internal static (int Level, int Limit) ParseLevelPair(string text, string fieldName)
    {
        if (!TryParseLevelPair(text, out var level, out var limit))
        {
            throw new InvalidOperationException($"无法从 {fieldName} OCR 结果中解析等级:{text}");
        }

        return (level, limit);
    }

    internal static bool TryParseLevelPair(string text, out int level, out int limit)
    {
        level = 0;
        limit = 0;
        var matches = NumberRegex.Matches(text);
        return matches.Count >= 2
               && int.TryParse(matches[0].Value, out level)
               && int.TryParse(matches[1].Value, out limit)
               && level > 0
               && limit > 0;
    }

    private static string OcrText(ImageRegion capture, Rect roi)

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Prefer the non-throwing `TryParseLevelPair` at call sites that already handle instability (the retry loops do).
  2. Re-align the level ROI to the current in-game layout.
  3. Improve OCR preprocessing so two numbers are reliably captured.
  4. If only calling `ParseLevelPair` directly, validate the text contains two numbers first.

Example fix

// before
var (lvl, lim) = ParseLevelPair(text, "角色等级"); // throws on 'Lv/90'

// after
if (TryParseLevelPair(text, out var lvl, out var lim))
    use(lvl, lim);
else
    logAndRetry(text);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!CharacterDevelopmentTask.TryParseLevelPair(text, out var level, out var limit))
    return; // or retry; avoid the throwing ParseLevelPair at unstable call sites

Type guard

static bool HasTwoPositiveNumbers(string text)
{
    var m = Regex.Matches(text, @"\d+");
    return m.Count >= 2 && m.Cast<Match>().All(x => int.Parse(x.Value) > 0);
}

Prevention

When it happens

Trigger: OCR returned partial text (only one number, or none); the ROI captured the wrong area; the level display uses a format the `\d+` regex splits differently; text like 'Lv.90' with a single visible number.

Common situations: Misaligned level ROI after a layout/resolution change; OCR dropping digits due to stylized fonts; the level cap not yet rendered.

Related errors


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