{"record":{"id":"43a1e907dad6af9b","repo":"babalae/better-genshin-impact","slug":"autoyuanqin-type","errorCode":null,"errorMessage":"不支持的 AutoYuanQin 曲谱类型：{type}","messagePattern":"不支持的 AutoYuanQin 曲谱类型：(.+?)","errorType":"exception","errorClass":"FormatException","httpStatus":null,"severity":"warning","filePath":"BetterGenshinImpact/GameTask/Music/Service/MusicScoreParser.cs","lineNumber":70,"sourceCode":"    private static async Task<PerformanceScore> ParseJsonAsync(\n        string path,\n        string rootFolder,\n        CancellationToken cancellationToken)\n    {\n        var text = await File.ReadAllTextAsync(path, cancellationToken);\n        var json = JObject.Parse(text);\n        var type = GetString(json, \"type\", \"yuanqin\").Trim().ToLowerInvariant();\n        var bpm = GetDouble(json, \"bpm\", 120);\n        var ticks = Math.Max(1, (int)Math.Round(GetDouble(json, \"ticks\", 480)));\n        var timeSignature = GetString(json, \"time_signature\", \"4/4\");\n        var notes = json[\"notes\"] ?? throw new FormatException(\"曲谱缺少 notes 字段\");\n\n        var format = type switch\n        {\n            \"yuanqin\" => MusicScoreFormat.YuanQin,\n            \"midi\" => MusicScoreFormat.MidiJson,\n            \"keyboard\" => MusicScoreFormat.Keyboard,\n            _ => throw new FormatException($\"不支持的 AutoYuanQin 曲谱类型：{type}\")\n        };\n\n        var timeline = format switch\n        {\n            MusicScoreFormat.YuanQin => ParseYuanQinTimeline(notes, bpm, timeSignature),\n            MusicScoreFormat.MidiJson => ParseMidiJsonTimeline(GetNotesString(notes, format), bpm, ticks),\n            MusicScoreFormat.Keyboard => ParseKeyboardTimeline(GetNotesString(notes, format), bpm),\n            _ => PerformanceTimeline.Empty\n        };\n\n        return new PerformanceScore\n        {\n            FullPath = path,\n            RelativePath = Path.GetRelativePath(rootFolder, path),\n            Name = GetString(json, \"name\", Path.GetFileNameWithoutExtension(path)),\n            Author = GetString(json, \"author\", \"未知作者\"),\n            Instrument = GetString(json, \"instrument\", \"风物之诗琴\"),\n            Description = GetString(json, \"description\", \"无描述\"),","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/GameTask/Music/Service/MusicScoreParser.cs#L52-L88","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var supportedTypes = new HashSet<string> { \"yuanqin\", \"midi\", \"keyboard\" };\nvar type = GetString(json, \"type\", \"yuanqin\").Trim().ToLowerInvariant();\nif (!supportedTypes.Contains(type))\n{\n    logger.LogError(\"不支持的曲谱类型：{Type}\", type);\n    return;\n}","typeGuard":"static bool IsSupportedScoreType(string type) => type is \"yuanqin\" or \"midi\" or \"keyboard\";","tryCatchPattern":"var score = await parser.ParseAsync(path, rootFolder, ct);\nif (!string.IsNullOrEmpty(score.Error)) { logger.LogWarning(\"曲谱解析失败：{Error}\", score.Error); }","preventionTips":["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."],"tags":["music","json","format-exception","user-content"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}