babalae/better-genshin-impact · critical · Exception
tp.json deserialization failed
Error message
tp.json deserialization failed
What it means
Thrown as a generic Exception by the MapLazyAssets constructor when Newtonsoft.Json's JObject.Parse(json)["data"] resolves to null and ToObject returns null. This means tp.json either lacks a top-level 'data' key or its value is JSON null. The teleport/dungeon/Goddess position data for the entire map depends on this array, so the singleton cannot be constructed.
Source
Thrown at BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.cs:45
{ "璃月", [270, -666] },
{ "稻妻", [-4400, -3050] },
{ "须弥", [2877, -374] },
{ "枫丹", [4515, 3631] },
{ "纳塔", [8973.5, -1879.1] },
{ "挪德卡莱", [9542.25, 1661.84] },
{ "至冬", [6755.051, 9480.659] }
};
public IReadOnlyDictionary<string, GiTpPosition> DomainPositionMap => _domainPositionMap;
public IReadOnlyDictionary<string, GiTpPosition> GoddessPositions => _goddessPositions;
public IReadOnlyList<string> DomainNameList => _domainNameList;
public IReadOnlyDictionary<string, List<GiTpPosition>> CountryToDomains => _countryToDomains;
private MapLazyAssets()
{
var json = File.ReadAllText(Global.Absolute(@"GameTask\AutoTrackPath\Assets\tp.json"));
var worldScenes = Newtonsoft.Json.Linq.JObject.Parse(json)["data"]?.ToObject<List<GiWorldScene>>() ?? throw new Exception("tp.json deserialization failed");
ScenesDic = worldScenes.ToDictionary(x => x.MapName, x => x);
// 取出秘境 description=Domain
var teyvatTpPositions = ScenesDic[nameof(MapTypes.Teyvat)].Points;
foreach (var tp in teyvatTpPositions.Where(tp => tp.Type == "BlessDomain" || tp.Type == "ForgeryDomain" || tp.Type == "MasteryDomain"))
{
_domainPositionMap[tp.Name!] = tp;
_domainNameList.Add(tp.Name!);
if (!string.IsNullOrEmpty(tp.Country))
{
if (!_countryToDomains.ContainsKey(tp.Country))
{
_countryToDomains[tp.Country] = [];
}
_countryToDomains[tp.Country].Add(tp);View on GitHub (pinned to a7cb36712d)
Solutions
- Restore GameTask/AutoTrackPath/Assets/tp.json from the repository — verify it has a 'data' array key.
- Validate the JSON with a linter to confirm the top-level structure is { "data": [ ... ] }.
- Check that the file was not truncated during git operations (verify file size).
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
var json = File.ReadAllText(path);
var parsed = Newtonsoft.Json.Linq.JObject.Parse(json);
if (parsed["data"] == null || parsed["data"]!.Type != Newtonsoft.Json.Linq.JTokenType.Array)
{
// tp.json missing 'data' array — abort
} Type guard
static bool IsValidTpJson(string json)
{
var token = Newtonsoft.Json.Linq.JObject.Parse(json)["data"];
return token != null && token.Type == Newtonsoft.Json.Linq.JTokenType.Array;
} Try / catch
try { MapLazyAssets.Get(); }
catch (Exception ex) when (ex.Message.Contains("tp.json")) { /* restore tp.json from repo */ } Prevention
- Include tp.json integrity check at startup.
- Version-control tp.json and verify it is not truncated after checkout.
When it happens
Trigger: tp.json at GameTask/AutoTrackPath/Assets/tp.json is missing the 'data' key, has "data": null, or is malformed JSON that JObject.Parse somehow accepted with a null data node.
Common situations: The tp.json file is corrupted, truncated, or from an incompatible version. A manual edit removed or renamed the 'data' field. The file was replaced with a different JSON structure. MapLazyAssets.Get() is called for the first time at startup, so this becomes a launch-time crash.
Related errors
- 无法解析 RecognitionObject 配置文件: {filePath}
- Failed to deserialize macro
- 解析配置组JSON配置失败
- Failed to deserialize JSON.
- repo.json 解析失败
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/feed336219c3ac05.
Report an issue: GitHub.