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
- Confirm the role name resolves to an avatar the account actually owns.
- Verify SetCurrentRoleFilter element/weapon detection (Recognizer.GetElementType/GetWeaponType) for that role — a wrong filter hides it.
- Increase MaxRoleSwitchAttempts for resilient runs, or surface a recoverable error instead of aborting the whole switch.
- 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
- Confirm the account owns every requested role before switching.
- Verify element/weapon filter detection for each role so the grid shows it.
- Log recognized slot names each attempt to spot recognizer false negatives.
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
- 切换角色:{nextRole.Slot} 号位连续 {MaxRoleSwitchAttempts} 次未能切换为 {ne
- 切换角色:换下错位角色后无法确定需要补回的槽位
- 切换角色:未指定角色或同一实际角色被指定到多个槽位
- 切换角色:未找到 {rebuildStartSlot} 号位的换下按钮
- 切换角色:筛选面板缺少武器筛选项
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/9f5062065ee75185.
Report an issue: GitHub.