babalae/better-genshin-impact · error · Exception

repo.json 解析失败

Error message

repo.json 解析失败

What it means

Thrown by ParseJson when repo.json parses as valid JSON but is missing one or more required fields: 'time', 'url', or 'file'. JObject.Parse succeeds, but indexing any of those keys returns null, failing the null-check. The repo.json schema requires all three keys.

Source

Thrown at BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs:1851

            return repoSubDir;
        }
        else
        {
            // 不存在 repo/ 目录,说明是 Git 仓库
            return repoJsonDir;
        }
    }

    private (string time, string url, string file) ParseJson(string jsonString)
    {
        var json = JObject.Parse(jsonString);
        var time = json["time"]?.ToString();
        var url = json["url"]?.ToString();
        var file = json["file"]?.ToString();
        // 检查是否有空值
        if (time is null || url is null || file is null)
        {
            throw new Exception("repo.json 解析失败");
        }

        return (time, url, file);
    }

    /// <summary>
    /// 统一的本地 zip 导入方法
    /// 解压后自动识别仓库内容,基于目录结构重合度决定覆盖已有仓库还是创建新文件夹,
    /// 并生成 repo_updated.json 更新标记
    /// </summary>
    /// <param name="zipFilePath">本地 zip 文件路径</param>
    /// <param name="onProgress">进度回调 (0-100, 描述文本)</param>
    /// <returns>导入后的仓库文件夹路径</returns>
    public async Task<string> ImportLocalRepoZip(string zipFilePath, Action<int, string>? onProgress = null)
    {
        await _repoWriteLock.WaitAsync();
        try
        {

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Open the offending repo.json and verify it contains non-null 'time', 'url', and 'file' keys.
  2. If the schema evolved, update ParseJson to read the new field names and/or make fields optional with sensible defaults.
  3. Before throwing, log the raw JSON and which key was missing to speed diagnosis.
  4. Validate repo.json against a schema (or a small validator) when it's first downloaded, rejecting bad manifests early.

Example fix

// before
var time = json["time"]?.ToString();
var url = json["url"]?.ToString();
var file = json["file"]?.ToString();
if (time is null || url is null || file is null)
    throw new Exception("repo.json 解析失败");

// after (name the missing field)
var missing = new[] { "time", "url", "file" }.Where(k => json[k] == null || json[k]!.Type == JTokenType.Null);
if (missing.Any())
    throw new FormatException($"repo.json 解析失败:缺少字段 {string.Join(", ", missing)}");
Defensive patterns

Strategy: validation

Validate before calling

// Validate required fields with names of missing keys
var required = new[] { "time", "url", "file" };
var missing = required.Where(k => json[k] == null || json[k]!.Type == JTokenType.Null).ToList();
if (missing.Count > 0)
    throw new FormatException($"repo.json 缺少字段: {string.Join(", ", missing)}");

Type guard

static bool IsValidRepoJson(JObject json) =>
    json["time"]?.Type == JTokenType.String &&
    json["url"]?.Type == JTokenType.String &&
    json["file"]?.Type == JTokenType.String;

Try / catch

catch (FormatException ex) when (ex.Message.Contains("repo.json"))
{
    _logger.LogError("repo.json 结构变化: {Msg}", ex.Message);
    Toast.Error($"仓库 manifest 格式不正确: {ex.Message}");
}

Prevention

When it happens

Trigger: ParseJson(jsonString) is called on repo.json content; JObject.Parse succeeds (it's valid JSON), but json["time"], json["url"], or json["file"] is null — the key is absent, or present but null-valued in the JSON.

Common situations: Upstream changed the repo.json schema and dropped/renamed a field; a hand-edited repo.json is malformed; an older/newer repo version uses different field names; the JSON contains the keys but with null values.

Related errors


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