babalae/better-genshin-impact · error · JsonException

翻译文件不是有效的 JSON 字典。

Error message

翻译文件不是有效的 JSON 字典。

What it means

JsonConvert.DeserializeObject<Dictionary<string,string>> returns null when the downloaded JSON is the literal "null" or content that deserializes to a null reference (not an object map). The null-coalescing throw converts that into a JsonException so a corrupt/empty file is never written to disk. Note: malformed JSON throws JsonException earlier and is swallowed by the outer catch, so this specific line only fires on JSON that is valid but null/non-object.

Source

Thrown at BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs:150

        {
            try
            {
                using var request = new HttpRequestMessage(HttpMethod.Get, url);
                request.Headers.UserAgent.ParseAdd("BetterGenshinImpact");
                using var response = await httpClient.SendAsync(request);
                if (response.StatusCode == HttpStatusCode.NotFound)
                {
                    lastError = new HttpRequestException("Language file not found.", null, response.StatusCode);
                    continue;
                }

                allNotFound = false;
                response.EnsureSuccessStatusCode();
                bytes = await response.Content.ReadAsByteArrayAsync();

                var json = Encoding.UTF8.GetString(bytes);
                _ = JsonConvert.DeserializeObject<Dictionary<string, string>>(json)
                    ?? throw new JsonException("翻译文件不是有效的 JSON 字典。");
                break;
            }
            catch (Exception e)
            {
                lastError = e;
                allNotFound = false;
            }
        }

        if (bytes == null)
        {
            if (allNotFound)
            {
                await ThemedMessageBox.WarningAsync($"语言文件不存在:{cultureName}.json");
                return;
            }

            throw new Exception($"下载语言文件失败:{cultureName}.json", lastError);

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Inspect the downloaded bytes before deserializing — reject empty/whitespace content early.
  2. Validate the result is a non-null, non-empty Dictionary before accepting it.
  3. Check the upstream bettergi-i18n repository for the given culture — the file may be empty or a stub.

Example fix

// before
_ = JsonConvert.DeserializeObject<Dictionary<string, string>>(json)
    ?? throw new JsonException("翻译文件不是有效的 JSON 字典。");

// after
if (string.IsNullOrWhiteSpace(json))
    throw new JsonException("翻译文件为空。");
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
if (dict is null || dict.Count == 0)
    throw new JsonException("翻译文件不是有效的 JSON 字典。");
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(json))
    throw new JsonException("翻译文件为空。");
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
if (dict is null || dict.Count == 0)
    throw new JsonException("翻译文件不是有效的 JSON 字典。");

Try / catch

try
{
    var dict = JsonConvert.DeserializeObject<Dictionary<string,string>>(json);
    if (dict is null || dict.Count == 0)
        throw new JsonException("翻译文件不是有效的 JSON 字典。");
}
catch (JsonException)
{
    // skip this mirror, try the next URL
    continue;
}

Prevention

When it happens

Trigger: A 200 response whose body is the JSON literal "null", an empty/whitespace body where DeserializeObject returns null, or a valid JSON scalar/array that the Dictionary binding resolves to null.

Common situations: Upstream repository file temporarily empty during a deploy; a mirror serving a placeholder; a CDN error page that is valid JSON but not a string->string object; content-type mismatch serving non-dict JSON.

Related errors


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