babalae/better-genshin-impact · error · PartySetupFailedException

切换角色:{slot.Slot} 号位角色识别为空

Error message

切换角色:{slot.Slot} 号位角色识别为空

What it means

BuildDesiredTeamRoles needs every current slot's name to merge requested roles with the existing party, but a TeamSlotSnapshot had Name==null — meaning avatar recognition for that slot scored below MatchThreshold in RecognizeTeamSlotsFromCharacterList. Without a name the merge (remaining list) cannot be built, so it fails.

Source

Thrown at BetterGenshinImpact/GameTask/Common/Job/SwitchCharacterStateMachineTask.cs:1035

                    return true;
                }
            }
        }

        return false;
    }

    /// <summary>
    /// 将显式目标与当前队伍合并为完整的期望队伍,未指定角色优先保留原物理位置。
    /// </summary>
    private static List<TargetRole> BuildDesiredTeamRoles(
        IReadOnlyCollection<TargetRole> requestedRoles,
        IReadOnlyList<TeamSlotSnapshot> currentSlots)
    {
        var desired = new TargetRole?[currentSlots.Count];
        var remaining = currentSlots
            .Select(slot => (slot.Slot, Name: slot.Name
                ?? throw new PartySetupFailedException($"切换角色:{slot.Slot} 号位角色识别为空")))
            .ToList();

        foreach (var role in requestedRoles.OrderBy(role => role.Slot))
        {
            desired[role.Slot - 1] = role;
            var currentIndex = remaining.FindIndex(item => role.Matches(item.Name));
            if (currentIndex >= 0)
            {
                remaining.RemoveAt(currentIndex);
            }
        }

        for (var index = 0; index < desired.Length; index++)
        {
            if (desired[index] != null)
            {
                continue;
            }

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Improve capture quality / resolution so recognition scores clear 0.7 for all slots.
  2. Extend AvatarGridIconRecognizer with the missing or low-confidence character icon.
  3. Re-run the recognition pass (trigger another _teamSnapshotDirty=true) before BuildDesiredTeamRoles so a fresh capture can resolve the null.
  4. If a name genuinely cannot resolve, surface it earlier in RecognizeTeamSlotsFromCharacterList (error 394 path) with full context.
Defensive patterns

Strategy: validation

Validate before calling

if (currentSlots.Any(slot => string.IsNullOrWhiteSpace(slot.Name)))
{
    _teamSnapshotDirty = true; // force a fresh recognition pass
    return; // re-recognize before building desired roles
}

Type guard

static bool AllSlotsNamed(IReadOnlyList<TeamSlotSnapshot> slots)
    => slots.All(slot => !string.IsNullOrWhiteSpace(slot.Name));

Try / catch

try { await switchTask.Start(...); }
catch (PartySetupFailedException ex) when (ex.Message.Contains("角色识别为空"))
{ _logger.LogWarning(ex, "存在槽位头像识别失败,建议重试或改善截图质量"); }

Prevention

When it happens

Trigger: RecognizeTeamSlotsFromCharacterList added a null entry to characterNames (candidate.Score < 0.7) which became a TeamSlotSnapshot with null Name; BuildDesiredTeamRoles then evaluates slot.Name ?? throw during the .Select projection.

Common situations: Avatar icon recognition confidence was low for one slot (lighting, costume, capture scale); the character grid partially occluded an avatar; recognizer model lacks that character's icon; transitional frame captured mid-scroll.

Related errors


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