babalae/better-genshin-impact · warning · FormatException
不支持的 AutoYuanQin 曲谱类型:{type}
Error message
不支持的 AutoYuanQin 曲谱类型:{type} What it means
Thrown by MusicScoreParser.ParseJsonAsync when the 'type' field in the JSON (lowercased, trimmed) is not one of 'yuanqin', 'midi', or 'keyboard'. The switch expression's default arm throws a FormatException. As with other parse errors, ParseAsync catches this and returns an invalid score.
Source
Thrown at BetterGenshinImpact/GameTask/Music/Service/MusicScoreParser.cs:70
private static async Task<PerformanceScore> ParseJsonAsync(
string path,
string rootFolder,
CancellationToken cancellationToken)
{
var text = await File.ReadAllTextAsync(path, cancellationToken);
var json = JObject.Parse(text);
var type = GetString(json, "type", "yuanqin").Trim().ToLowerInvariant();
var bpm = GetDouble(json, "bpm", 120);
var ticks = Math.Max(1, (int)Math.Round(GetDouble(json, "ticks", 480)));
var timeSignature = GetString(json, "time_signature", "4/4");
var notes = json["notes"] ?? throw new FormatException("曲谱缺少 notes 字段");
var format = type switch
{
"yuanqin" => MusicScoreFormat.YuanQin,
"midi" => MusicScoreFormat.MidiJson,
"keyboard" => MusicScoreFormat.Keyboard,
_ => throw new FormatException($"不支持的 AutoYuanQin 曲谱类型:{type}")
};
var timeline = format switch
{
MusicScoreFormat.YuanQin => ParseYuanQinTimeline(notes, bpm, timeSignature),
MusicScoreFormat.MidiJson => ParseMidiJsonTimeline(GetNotesString(notes, format), bpm, ticks),
MusicScoreFormat.Keyboard => ParseKeyboardTimeline(GetNotesString(notes, format), bpm),
_ => PerformanceTimeline.Empty
};
return new PerformanceScore
{
FullPath = path,
RelativePath = Path.GetRelativePath(rootFolder, path),
Name = GetString(json, "name", Path.GetFileNameWithoutExtension(path)),
Author = GetString(json, "author", "未知作者"),
Instrument = GetString(json, "instrument", "风物之诗琴"),
Description = GetString(json, "description", "无描述"),View on GitHub (pinned to a7cb36712d)
Solutions
- Set the 'type' field in the JSON to one of: 'yuanqin', 'midi', or 'keyboard'.
- Omit the 'type' field entirely to default to 'yuanqin'.
- Check the PerformanceScore.Error property returned by ParseAsync for the exact unsupported type value.
- If a new format is needed, add a case to the switch and implement the corresponding timeline parser.
Defensive patterns
Strategy: validation
Validate before calling
var supportedTypes = new HashSet<string> { "yuanqin", "midi", "keyboard" };
var type = GetString(json, "type", "yuanqin").Trim().ToLowerInvariant();
if (!supportedTypes.Contains(type))
{
logger.LogError("不支持的曲谱类型:{Type}", type);
return;
} Type guard
static bool IsSupportedScoreType(string type) => type is "yuanqin" or "midi" or "keyboard";
Try / catch
var score = await parser.ParseAsync(path, rootFolder, ct);
if (!string.IsNullOrEmpty(score.Error)) { logger.LogWarning("曲谱解析失败:{Error}", score.Error); } Prevention
- Set 'type' to a supported value or omit it to default to 'yuanqin'.
- Validate the type field against the supported set before parsing.
- Check PerformanceScore.Error for user-facing feedback.
When it happens
Trigger: Loading a .json score file whose 'type' field has a value other than the three supported formats. If 'type' is omitted, it defaults to 'yuanqin' via GetString and does not trigger this error.
Common situations: A score file from an incompatible tool that uses a different type identifier (e.g. 'lyre', 'zither'); a typo in the type field; a future/unrecognized format string.
Related errors
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/43a1e907dad6af9b.
Report an issue: GitHub.