babalae/better-genshin-impact · error · FormatException
键谱缺少右括号:{closing.Value}
Error message
键谱缺少右括号:{closing.Value} What it means
A FormatException from ParseKeyboardNodes thrown at end-of-text when a closing parameter was expected (closing.HasValue) but never matched. Each recursive call expects its specific closer; reaching the end of the string without it means an opening bracket was never closed.
Source
Thrown at BetterGenshinImpact/GameTask/Music/Service/MusicScoreParser.cs:538
}
else
{
node = new KeyboardNode('\0', current, []);
index++;
}
while (index < text.Length && text[index] == '-')
{
node.Multiplier++;
index++;
}
nodes.Add(node);
}
if (closing.HasValue)
{
throw new FormatException($"键谱缺少右括号:{closing.Value}");
}
return nodes;
}
private static void UnfoldKeyboardNode(
KeyboardNode node,
double startBeat,
double durationBeat,
ICollection<KeyboardNote> output)
{
if (node.Value.HasValue)
{
var key = char.ToUpperInvariant(node.Value.Value);
if (key != '0' && SupportedKeys.Contains(key))
{
output.Add(new KeyboardNote(key, startBeat, 0, durationBeat));
}View on GitHub (pinned to a7cb36712d)
Solutions
- Add the missing closing bracket indicated by {closing.Value} (e.g. append ')' for an unclosed '(').
- Use a bracket-matching editor to verify the structure.
- Route through ParseAsync to surface InvalidScore.Error.
- Lint the score for bracket balance before parsing.
Example fix
// before "notes":"(QW-" // after "notes":"(QW-)"
Defensive patterns
Strategy: validation
Validate before calling
static bool AllBracketsClosed(string s)
{
var st = new Stack<char>();
foreach (var c in s)
{
if (c is '(' or '[' or '{') st.Push(c);
else if (c is ')' or ']' or '}') { if (st.Count == 0) return false; st.Pop(); }
}
return st.Count == 0;
} Type guard
null
Try / catch
var score = await parser.ParseAsync(path, root, ct);
if (!string.IsNullOrEmpty(score.Error)) { Log.Warning(score.Error); continue; } Prevention
- Balance every opening bracket with its matching closer.
- Lint before parse to catch unclosed groups.
- Use ParseAsync for InvalidScore reporting.
When it happens
Trigger: A keyboard-score string with an unclosed bracket, e.g. '(QW', '[AB', or '{CD'. The message echoes the expected closing character.
Common situations: Truncated score; manual editing that deleted a closing bracket; a group nested incorrectly so the closer landed at the wrong scope.
Related errors
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/5760e93db4d60688.
Report an issue: GitHub.