babalae/better-genshin-impact · error · Exception
读取文件失败: {ex.Message}
Error message
读取文件失败: {ex.Message} What it means
Thrown by FileAccessBridge.ReadFile's catch-all: any exception inside ReadFile (UnauthorizedAccessException, FileNotFoundException, IOException, etc.) is wrapped and re-thrown as a generic Exception with prefix '读取文件失败: '. This destroys the original exception type and stack origin.
Source
Thrown at BetterGenshinImpact/Core/Script/WebView/FileAccessBridge.cs:71
}
}
public string ReadFile(string relativePath)
{
try
{
var fullPath = Path.Combine(_allowedDirectory, relativePath);
if (!IsPathAllowed(fullPath))
throw new UnauthorizedAccessException($"访问路径 '{relativePath}' 被拒绝");
if (!File.Exists(fullPath))
throw new FileNotFoundException($"文件 '{relativePath}' 不存在");
return File.ReadAllText(fullPath, Encoding.UTF8);
}
catch (Exception ex)
{
throw new Exception($"读取文件失败: {ex.Message}");
}
}
public void WriteFile(string relativePath, string content)
{
try
{
var fullPath = Path.Combine(_allowedDirectory, relativePath);
if (!IsPathAllowed(fullPath))
throw new UnauthorizedAccessException($"访问路径 '{relativePath}' 被拒绝");
// var directory = Path.GetDirectoryName(fullPath);
// if (!string.IsNullOrEmpty(directory))
// Directory.CreateDirectory(directory);
File.WriteAllText(fullPath, content, new UTF8Encoding(false));
}
catch (Exception ex)View on GitHub (pinned to a7cb36712d)
Solutions
- Remove the catch-all rewrap; let the specific exception (UnauthorizedAccessException, FileNotFoundException, IOException) propagate so callers can handle by type.
- If a uniform exception type is required, use a custom exception type that preserves the original as InnerException and rethrow with ExceptionDispatchInfo.Capture(ex).Throw() to keep the stack.
- At minimum, log the full exception before rewrapping.
Example fix
// before
public string ReadFile(string relativePath)
{
try { /* ... */ }
catch (Exception ex) { throw new Exception($"读取文件失败: {ex.Message}"); }
}
// after (let specific exceptions propagate; only wrap unexpected IO errors preserving InnerException)
public string ReadFile(string relativePath)
{
var fullPath = Path.Combine(_allowedDirectory, relativePath);
if (!IsPathAllowed(fullPath)) throw new UnauthorizedAccessException($"访问路径 '{relativePath}' 被拒绝");
if (!File.Exists(fullPath)) throw new FileNotFoundException($"文件 '{relativePath}' 不存在", fullPath);
return File.ReadAllText(fullPath, Encoding.UTF8); // IOException propagates as-is
} Defensive patterns
Strategy: try-catch
Try / catch
// Remove the catch-all; let specific exceptions propagate:
// - UnauthorizedAccessException (sandbox)
// - FileNotFoundException (missing)
// - IOException (locked/disk)
// If you must wrap, preserve InnerException:
catch (Exception ex)
{
throw new FileAccessBridgeException("读取文件失败", ex);
} Prevention
- Do not catch-all and rewrap — it destroys the original type and stack.
- If uniformity is required, define a custom exception that carries InnerException.
- Log the full exception before rewrapping if you must rewrap.
When it happens
Trigger: Any exception in the try block of ReadFile — sandbox denial (135), missing file (136), IO error, encoding error, or File.ReadAllText failure — is caught by `catch (Exception ex)` and rewrapped.
Common situations: The underlying error is one of 135/136 or an IOException (locked file, disk error); the rewrap hides the original type so callers cannot distinguish UnauthorizedAccessException from FileNotFoundException.
Related errors
- 写入文件失败: {ex.Message}
- 文件 '{relativePath}' 不存在
- 列出项目失败: {ex.Message}
- 仓库文件夹不存在,请至少成功更新一次仓库!
- 找不到原始 repo.json 文件
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/2ccbbc6473ab87ef.
Report an issue: GitHub.