babalae/better-genshin-impact · error · InvalidDataException
武器名称表中没有可用的武器。
Error message
武器名称表中没有可用的武器。
What it means
Thrown by WeaponNameMatcher.MatchClosest when the weaponNames collection passed to it is empty (Count == 0). The internal lazy-loaded name table is populated from item.csv; this error means either the CSV failed to yield any weapon names or a caller passed an empty list. The guard exists so the subsequent LINQ OrderBy/Take does not produce an empty candidates array that would cause an IndexOutOfRangeException.
Source
Thrown at BetterGenshinImpact/GameTask/CharacterDevelopment/WeaponNameMatcher.cs:56
public static WeaponNameMatch Match(string ocrText)
{
return MatchClosest(ocrText, WeaponNames.Value);
}
/// <summary>
/// 在给定名称表中选择编辑距离最小的名称,并判断该候选是否足够可信。
/// </summary>
internal static WeaponNameMatch MatchClosest(string ocrText, IReadOnlyList<string> weaponNames)
{
var normalizedText = ocrText.Trim();
if (string.IsNullOrWhiteSpace(normalizedText))
{
throw new InvalidOperationException("武器名称 OCR 结果为空。");
}
if (weaponNames.Count == 0)
{
throw new InvalidDataException("武器名称表中没有可用的武器。");
}
var candidates = weaponNames
.Select(name =>
{
var distance = LevenshteinDistance(normalizedText, name);
var maximumLength = Math.Max(normalizedText.Length, name.Length);
var similarity = 1d - (double)distance / maximumLength;
return new WeaponNameMatch(name, distance, similarity, false);
})
.OrderBy(match => match.Distance)
.ThenBy(match => match.Name, StringComparer.Ordinal)
.Take(2)
.ToArray();
var best = candidates[0];
var distanceMargin = candidates.Length == 1
? int.MaxValueView on GitHub (pinned to a7cb36712d)
Solutions
- If calling MatchClosest directly, guard with a non-empty check before invoking it.
- Verify the bundled Assets/Model/ItemV2/item.csv exists and contains rows whose item_class_id starts with 'weapon:'.
- Rebuild/reinstall the application from a known-good source if the asset file is corrupted.
Example fix
// before
var match = WeaponNameMatcher.MatchClosest(ocrText, myWeaponNames);
// after
if (myWeaponNames.Count == 0) { /* handle: no weapon data loaded */ return; }
var match = WeaponNameMatcher.MatchClosest(ocrText, myWeaponNames); Defensive patterns
Strategy: validation
Validate before calling
if (weaponNames == null || weaponNames.Count == 0)
{
// handle missing weapon data — do not call MatchClosest
return;
} Type guard
static bool HasWeaponNames(IReadOnlyList<string> names) => names != null && names.Count > 0;
Try / catch
try { var match = WeaponNameMatcher.MatchClosest(text, names); }
catch (InvalidDataException) { /* weapon name table empty — log and skip */ } Prevention
- Verify item.csv is present and contains weapon rows before running weapon OCR correction.
- If calling MatchClosest directly, always pre-check the list is non-empty.
When it happens
Trigger: Calling WeaponNameMatcher.Match(ocrText) when the lazy WeaponNames.Value resolved to zero entries — i.e., ExtractWeaponNames returned an empty set that somehow bypassed its own empty-set guard, or calling MatchClosest directly with an empty IReadOnlyList<string>.
Common situations: The item.csv shipped with the build is missing or truncated so no weapon: rows exist (normally caught earlier by [342], but a corrupt build could let an empty list through). A custom caller unit-testing MatchClosest passes an empty weapon name list.
Related errors
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/75a018791fd14230.
Report an issue: GitHub.