babalae/better-genshin-impact · error · InvalidOperationException

角色养成识别:头像识别器尚未初始化。

Error message

角色养成识别:头像识别器尚未初始化。

What it means

Thrown by the `Recognizer` property getter when `_recognizer` is null. The avatar-grid icon recognizer is only created inside `Start()` (assigned at line 311) and deliberately nulled in its `finally` block (line 337), so the field is non-null only for the duration of an active state-machine run. Accessing it outside that window is treated as a usage-contract violation rather than a recoverable runtime condition.

Source

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

    private readonly CharacterDevelopmentAssets _assets;

    private CharacterDevelopmentState _workflowState = CharacterDevelopmentState.OpenCharacterList;
    private AvatarGridIconRecognizer? _recognizer;
    private int _characterIndex;
    private CharacterSelectionTarget? _currentTarget;
    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));
        }

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Drive the task only through `await task.Start(ct)` — it owns recognizer creation and disposal.
  2. If you need the recognizer in a test, construct an `AvatarGridIconRecognizer` yourself and pass it to the helper methods that accept one.
  3. Do not read `Recognizer` from cleanup/continuation code that may run after `Start` has finished.

Example fix

// before
var task = new CharacterDevelopmentStateMachineTask(names, cats);
var r = task.Recognizer; // throws: not started

// after
await task.Start(ct); // recognizer lives only inside Start
Defensive patterns

Strategy: validation

Validate before calling

// Recognizer/CurrentTarget/CurrentResult are valid only inside Start();
// do not access them outside a running state machine.
if (task is null || !isRunning) return; // guard caller code paths

Prevention

When it happens

Trigger: Calling a `[StateHandler]`/`[StateDetector]` method directly on a `CharacterDevelopmentStateMachineTask` instance without going through `Start()`, or holding a reference to the task and reading `Recognizer` after `Start` has returned/thrown.

Common situations: Unit tests that invoke handler methods in isolation; a subclass or extension that calls handlers manually; logic that runs in a `finally`/continuation after the recognizer has already been disposed and nulled.

Related errors


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