babalae/better-genshin-impact · error · PartySetupFailedException

切换角色:{refillRole.Slot} 号位连续 {MaxRoleSwitchAttempts} 次未能补回 {r

Error message

切换角色:{refillRole.Slot} 号位连续 {MaxRoleSwitchAttempts} 次未能补回 {refillRole.Name}

What it means

Thrown during the suffix-rebuild refill phase when a single slot has exhausted its retry budget: _roleSwitchAttempts for the peeked refillRole.Slot has reached MaxRoleSwitchAttempts (3). The role could not be added back to the team after 3 consecutive attempts.

Source

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

                if (!TryClickText(page, "换下", Rect1080(382, 994, 87, 51)))
                {
                    throw new PartySetupFailedException($"切换角色:未找到 {rebuildStartSlot} 号位的换下按钮");
                }

                await WaitForRoleRemoved(rebuildStartSlot, _ct);
                _expectedTeamCount--;
                _teamSnapshotDirty = true;
                return StateHandlerResult.Wait;
            }

            _isRebuildClearing = false;

            if (_rebuildRoles.Count > 0)
            {
                var refillRole = _rebuildRoles.Peek();
                if (_roleSwitchAttempts.GetValueOrDefault(refillRole.Slot) >= MaxRoleSwitchAttempts)
                {
                    throw new PartySetupFailedException(
                        $"切换角色:{refillRole.Slot} 号位连续 {MaxRoleSwitchAttempts} 次未能补回 {refillRole.Name}");
                }

                SetCurrentRole(refillRole);
                _isAppendingRole = refillRole.Slot > _currentTeamSlots.Count;
                ClickFixedTeamSlot(refillRole.Slot);
                _workflowState = SwitchCharacterState.OpenFilterPanel;
                return StateHandlerResult.Success;
            }

            _rebuildStartSlot = null;
        }

        if (_currentRole == null)
        {
            var currentNameBySlot = _currentTeamSlots.ToDictionary(slot => slot.Slot, slot => slot.Name);
            var nextRole = _requestedTargetRoles
                .OrderBy(role => role.Slot)

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Confirm the role name resolves to an avatar the account actually owns.
  2. Verify SetCurrentRoleFilter element/weapon detection (Recognizer.GetElementType/GetWeaponType) for that role — a wrong filter hides it.
  3. Increase MaxRoleSwitchAttempts for resilient runs, or surface a recoverable error instead of aborting the whole switch.
  4. Log each attempt's recognized slot name to see why Matches() keeps failing.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate roster ownership before starting the switch
foreach (var name in new[] { slot1, slot2, slot3, slot4 }.Where(s => !string.IsNullOrWhiteSpace(s)))
{
    var standard = ToConfiguredAvatarName(name.Trim());
    if (!DefaultAutoFightConfig.CombatAvatarMap.ContainsKey(standard) && !IsOwnedAvatar(standard))
        throw new ArgumentException($"账号未拥有角色:{standard}");
}

Type guard

static bool RoleIsOwned(string name)
{
    var standard = ToConfiguredAvatarName(name.Trim());
    return DefaultAutoFightConfig.CombatAvatarMap.ContainsKey(standard) || IsOwnedAvatar(standard);
}

Try / catch

try { await sm.Start(s1, s2, s3, s4, usePhysicalSlots, ct); }
catch (PartySetupFailedException e) when (e.Message.Contains("未能补回"))
{ /* skip the unattainable slot and continue with remaining roles, or alert the user */ }

Prevention

When it happens

Trigger: In HandlePrepareNextRole, _rebuildRoles.Peek() is a refillRole and _roleSwitchAttempts[refillRole.Slot] >= 3. Each prior OpenFilterPanel/select/save cycle for that slot failed to land the named role, incrementing the attempt counter until the cap.

Common situations: The named role is not owned/unlocked; the role's filter (element/weapon) is wrong so the avatar is never shown; the recognizer mis-identifies the placed avatar so Matches() stays false; UI lag drops a confirm click; an alias resolves to a name not present in the player's roster.

Related errors


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