babalae/better-genshin-impact · warning · FormatException

yuanqin 音符数组中包含非对象元素

Error message

yuanqin 音符数组中包含非对象元素

What it means

Thrown by MusicScoreParser.ParseYuanQinTokens(JArray) when iterating over the notes JSON array and encountering an element that is not a JObject. The yuanqin array form requires each note to be a JSON object with 'note' and optionally 'spl' and 'type' fields. A primitive element (string, number, boolean, null) inside the array triggers this FormatException.

Source

Thrown at BetterGenshinImpact/GameTask/Music/Service/MusicScoreParser.cs:345

                    out var denominator))
            {
                throw new FormatException($"无法解析音符 {keys} 的时值:{value}");
            }

            tokens.Add(new YuanQinToken(keys, denominator, special));
        }

        return tokens;
    }

    private static List<YuanQinToken> ParseYuanQinTokens(JArray notes)
    {
        var tokens = new List<YuanQinToken>(notes.Count);
        foreach (var item in notes)
        {
            if (item is not JObject note)
            {
                throw new FormatException("yuanqin 音符数组中包含非对象元素");
            }

            var keys = GetString(note, "note", string.Empty);
            if (string.IsNullOrWhiteSpace(keys))
            {
                throw new FormatException("yuanqin 音符对象缺少 note 字段");
            }

            var special = GetString(note, "spl", "none");
            if (special is "^" or "&")
            {
                tokens.Add(new YuanQinToken(keys, 0, special));
                continue;
            }

            if (!double.TryParse(
                    note["type"]?.ToString(),
                    NumberStyles.Float,

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Ensure every element in the notes array is a JSON object with at least a 'note' field (string of keys).
  2. Remove or convert any non-object elements (bare strings, numbers) in the array.
  3. Validate the array schema: each element must be an object like {"note":"Q", "type":"1", "spl":"none"}.
Defensive patterns

Strategy: validation

Validate before calling

// Validate notes array elements are all objects
if (notes is JArray arr)
{
    foreach (var item in arr)
    {
        if (item is not JObject)
            logger.LogError("notes 数组包含非对象元素:{Item}", item);
    }
}

Type guard

static bool AreAllNotesObjects(JArray notes) => notes.All(i => i is JObject);

Try / catch

var score = await parser.ParseAsync(path, rootFolder, ct);
if (!string.IsNullOrEmpty(score.Error)) { logger.LogWarning(score.Error); }

Prevention

When it happens

Trigger: A yuanqin score where 'notes' is a JSON array but contains mixed types — e.g. [{"note":"Q","type":"1"}, "W", 42]. Only objects are accepted; the string or number element causes the throw.

Common situations: Manual editing of the score JSON inserting a bare string or number instead of an object; a converter tool producing inconsistent array element types.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/39870e8ffd8d708f. Report an issue: GitHub.