babalae/better-genshin-impact · error · FileNotFoundException

无法解析模块导入路径: '{specifier}'

Error message

无法解析模块导入路径: '{specifier}'

What it means

Thrown by PackageDocumentLoader.LoadDocumentAsync when a JS module import specifier cannot be resolved to an existing file on disk. The loader first tries ResolvePhysicalPath (ClearScript's default resolution), then falls back to stripping relative prefixes and combining with the script root path. If both fail, this FileNotFoundException is thrown with the original specifier.

Source

Thrown at BetterGenshinImpact/Core/Script/PackageDocumentLoader.cs:42

            // ResolvePhysicalPath 可能因 sourceInfo 为空而失败,直接从脚本根目录兜底
            if (targetPath == null || !File.Exists(targetPath))
            {
                var stripped = Regex.Replace(specifier, @"^(?:\.\.?/)+", "");
                if (!Path.IsPathRooted(stripped))
                {
                    var fullPath = Path.GetFullPath(Path.Combine(_scriptRootPath, stripped));
                    if (fullPath.StartsWith(_scriptRootPath, StringComparison.OrdinalIgnoreCase)
                        && File.Exists(fullPath))
                    {
                        targetPath = fullPath;
                    }
                }
            }

            if (targetPath == null || !File.Exists(targetPath))
            {
                throw new FileNotFoundException($"无法解析模块导入路径: '{specifier}'", specifier);
            }

            // 处理 JS 文件的重写
            if (Path.GetExtension(targetPath).ToLower() == ".js")
            {
                var uri = new Uri(targetPath);

                // 检查缓存
                var cached = GetCachedDocument(uri);
                if (cached != null) return cached;

                string content = await File.ReadAllTextAsync(targetPath);
                string processedCode = RewriteScriptCode(content, targetPath);
                var documentInfo = new DocumentInfo(uri) { Category = ModuleCategory.Standard };
                return CacheDocument(new StringDocument(documentInfo, processedCode), false);
            }

            throw new FileNotFoundException($"不支持的模块导入类型: '{specifier}' (仅支持 .js 文件)", specifier);

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Verify the imported file exists at the resolved path — check spelling and case.
  2. Use correct relative path depth from the importing file, or use the packages/ root convention.
  3. Ensure the file has a .js extension (the loader only resolves .js files for module imports).
  4. Check the error's FileName property (the specifier) to identify which import failed.

Example fix

// before
import { helper } from './util/helpers';
// after
import { helper } from './util/helpers.js';
Defensive patterns

Strategy: validation

Validate before calling

string resolvedPath = Path.IsPathRooted(specifier)
    ? specifier
    : Path.GetFullPath(Path.Combine(scriptRoot, specifier));
if (!File.Exists(resolvedPath))
    throw new FileNotFoundException($"Module not found: {specifier}");

Type guard

static bool IsModuleResolvable(string specifier, string scriptRoot)
{
    var stripped = System.Text.RegularExpressions.Regex.Replace(specifier, @"^(?:\.\.?/)+", "");
    var fullPath = Path.GetFullPath(Path.Combine(scriptRoot, stripped));
    return fullPath.StartsWith(scriptRoot, StringComparison.OrdinalIgnoreCase) && File.Exists(fullPath);
}

Prevention

When it happens

Trigger: A JS script uses import ... from './module' or import ... from 'packages/foo' where the target file doesn't exist relative to either the importing file or the script root. Common with typos, missing file extensions (the loader expects explicit paths), or case-sensitivity issues on case-sensitive filesystems.

Common situations: Script package author references a module file that wasn't included in the distribution. Relative import path depth is wrong (e.g. '../../utils' vs '../../../utils'). File renamed or moved but import not updated. Case mismatch on Linux (e.g. 'Utils.js' vs 'utils.js').

Related errors


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