babalae/better-genshin-impact · error · InvalidOperationException

角色养成识别:当前结果尚未初始化。

Error message

角色养成识别:当前结果尚未初始化。

What it means

Thrown by the `CurrentResult` property getter when `_currentResult` is null. `_currentResult` is created in `PrepareCharacter` (line 345) alongside `_currentTarget`. It accumulates the recognized attributes/weapon/talent for the active character and is pushed into `_results`. Like the other lazy properties, it is non-null only during an active run for the current character.

Source

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

    private CharacterDevelopmentResult? _currentResult;
    private Queue<CharacterDevelopmentCategory> _pendingCategories = new();
    private CharacterDevelopmentCategory _currentCategory;
    private string? _pendingElementType;
    private string? _pendingWeaponType;
    private List<Point> _talentPoints = [];
    private int _talentIndex;
    private readonly HashSet<string> _readTalentTypes = new(StringComparer.Ordinal);

    protected override ILogger Logger => _logger;

    private AvatarGridIconRecognizer Recognizer =>
        _recognizer ?? throw new InvalidOperationException("角色养成识别:头像识别器尚未初始化。");

    private CharacterSelectionTarget CurrentTarget =>
        _currentTarget ?? throw new InvalidOperationException("角色养成识别:当前角色尚未初始化。");

    private CharacterDevelopmentResult CurrentResult =>
        _currentResult ?? throw new InvalidOperationException("角色养成识别:当前结果尚未初始化。");

    public CharacterDevelopmentStateMachineTask(IReadOnlyList<string> characterNames, CharacterDevelopmentCategory categories)
    {
        if (characterNames.Count == 0)
        {
            throw new ArgumentException("至少需要指定一个角色。", nameof(characterNames));
        }

        if (categories == CharacterDevelopmentCategory.None)
        {
            throw new ArgumentException("至少需要指定一个读取分类。", nameof(categories));
        }

        _categories = categories;
        _targets = characterNames.Select(CharacterSelectionHelper.CreateTarget).ToList();
        var captureRect = TaskContext.Instance().SystemInfo.ScaleMax1080PCaptureRect;
        _assets = CharacterDevelopmentAssets.Get(captureRect.Width, captureRect.Height);

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Use `Start()` as the only entry point — it guarantees `PrepareCharacter(0)` runs first.
  2. To obtain results, read the `List<CharacterDevelopmentResult>` returned by `Start()` rather than `CurrentResult`.
  3. Do not read `CurrentResult` from cleanup or post-run code.

Example fix

// before
var result = task.CurrentResult; // throws if not running

// after
var results = await task.Start(ct); // use the returned list
Defensive patterns

Strategy: validation

Validate before calling

// CurrentResult is per-active-character and only valid during Start().
// Use the returned results list: var results = await task.Start(ct);

Prevention

When it happens

Trigger: Reading `CurrentResult` before `PrepareCharacter` has run, or from code outside the `Start()` execution window.

Common situations: Direct handler invocation in tests; accessing results mid-run from another thread before `PrepareCharacter` completes; reading the property after `Start` returns.

Related errors


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