babalae/better-genshin-impact · critical · Exception

地图数据加载失败,文件: {matFilePath}

Error message

地图数据加载失败,文件: {matFilePath}

What it means

Companion to error 403, thrown one line later when FeatureStorageHelper.LoadDescriptorMat(matFilePath) returns null. LoadDescriptorMat returns null only when File.Exists(descriptorPath) is false; otherwise it reads the image and converts it. So this means the descriptor .mat.png file for the floor does not exist on disk.

Source

Thrown at BetterGenshinImpact/GameTask/Common/Map/Maps/Base/BaseMapLayer.cs:97

            }

            return int.TryParse(parts[1], out var floor) ? floor : throw new Exception($"分层地图数据文件夹中中存在无法解析的文件名: {fileName}");
        });

        foreach (var group in groupedFiles)
        {
            var floor = group.Key;
            var layer = new BaseMapLayer(baseMap) { Floor = floor };

            // 查找特征文件路径
            var kpFilePath = group.First(f => f.EndsWith(".kp.bin"));
            var matFilePath = group.First(f => f.EndsWith(".mat.png"));

            SpeedTimer speedTimer = new($"加载 {Path.GetFileNameWithoutExtension(kpFilePath)} 地图特征");
            // 加载特征数据
            layer.TrainKeyPoints = FeatureStorageHelper.LoadKeyPointArray(kpFilePath) ?? throw new Exception($"地图数据加载失败,文件: {kpFilePath}");
            speedTimer.Record("特征点");
            layer.TrainDescriptors = FeatureStorageHelper.LoadDescriptorMat(matFilePath) ?? throw new Exception($"地图数据加载失败,文件: {matFilePath}");
            speedTimer.Record("特征描述");

            // 切割特征数据
            if (baseMap.SplitRow > 0 || baseMap.SplitCol > 0)
            {
                layer.SplitBlocks = KeyPointFeatureBlockHelper.SplitFeatures(baseMap.MapSize, baseMap.SplitRow, baseMap.SplitCol, layer.TrainKeyPoints, layer.TrainDescriptors);
                speedTimer.Record("切割特征点");
            }

            speedTimer.DebugPrint();

            layers.Add(layer);
        }

        // 从 0, -1, -2 这样的顺序对这个list排序
        layers.Sort((a, b) =>
        {
            if (a.Floor == b.Floor)

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Confirm both '<name>.kp.bin' and '<name>.mat.png' exist together for every floor in Assets\Map\<Type>.
  2. Regenerate the full dataset so pairs are always produced together.
  3. Add a pre-load validation pass that checks each group has both extensions before attempting to load.
Defensive patterns

Strategy: validation

Validate before calling

// Verify each group has BOTH a kp and a mat file before loading
foreach (var g in groupedFiles)
{
    if (!g.Any(f => f.EndsWith(".kp.bin")) || !g.Any(f => f.EndsWith(".mat.png")))
        throw new Exception($"楼层 {g.Key} 缺少配对的 .kp.bin 或 .mat.png");
}

Prevention

When it happens

Trigger: After the keypoint file loaded successfully, the code loads matFilePath = group.First(f => f.EndsWith(".mat.png")) and calls LoadDescriptorMat, which returns null because the .mat.png is absent. This usually indicates an incomplete dataset: the .kp.bin is present but its paired .mat.png is not.

Common situations: Partial dataset where a .kp.bin exists but the matching .mat.png was not generated/copied; file copy interrupted; generation tool failed midway and wrote only one of the pair.

Related errors


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