{"record":{"id":"a404584d9ca6e6ea","repo":"babalae/better-genshin-impact","slug":"ex-message-a40458","errorCode":null,"errorMessage":"写入文件失败: {ex.Message}","messagePattern":"写入文件失败: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Script/WebView/FileAccessBridge.cs","lineNumber":91,"sourceCode":"    }\n\n    public void WriteFile(string relativePath, string content)\n    {\n        try\n        {\n            var fullPath = Path.Combine(_allowedDirectory, relativePath);\n            if (!IsPathAllowed(fullPath))\n                throw new UnauthorizedAccessException($\"访问路径 '{relativePath}' 被拒绝\");\n\n            // var directory = Path.GetDirectoryName(fullPath);\n            // if (!string.IsNullOrEmpty(directory))\n            //     Directory.CreateDirectory(directory);\n\n            File.WriteAllText(fullPath, content, new UTF8Encoding(false));\n        }\n        catch (Exception ex)\n        {\n            throw new Exception($\"写入文件失败: {ex.Message}\");\n        }\n    }\n\n    public bool FileExists(string relativePath)\n    {\n        try\n        {\n            var fullPath = Path.Combine(_allowedDirectory, relativePath);\n            if (!IsPathAllowed(fullPath))\n                return false;\n\n            return File.Exists(fullPath);\n        }\n        catch\n        {\n            return false;\n        }\n    }","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Script/WebView/FileAccessBridge.cs#L73-L109","documentation":"Thrown by FileAccessBridge.WriteFile's catch-all: any exception (UnauthorizedAccessException from 138, IOException from a locked/read-only target, disk-full, etc.) is rewrapped as a generic Exception with prefix '写入文件失败: '. Same anti-pattern as error 137 on the write path.","triggerScenarios":"Any exception in WriteFile's try block is caught by `catch (Exception ex)` and re-thrown as new Exception(\"写入文件失败: \" + ex.Message), losing the original type.","commonSituations":"Underlying cause is sandbox denial (138), file is read-only/locked, destination directory missing (note: directory creation is commented out on lines 83-85!), or disk full. The rewrap hides which occurred.","solutions":["Remove the catch-all rewrap; let UnauthorizedAccessException and IOException propagate with their original types.","Uncomment the Directory.CreateDirectory block (lines 83-85) so writing to a not-yet-existing subdirectory doesn't fail — but only after confirming the path passed IsPathAllowed.","If a uniform type is needed, preserve InnerException and use ExceptionDispatchInfo to keep the stack."],"exampleFix":"// before\npublic void WriteFile(string relativePath, string content)\n{\n    try\n    {\n        var fullPath = Path.Combine(_allowedDirectory, relativePath);\n        if (!IsPathAllowed(fullPath)) throw new UnauthorizedAccessException($\"访问路径 '{relativePath}' 被拒绝\");\n        File.WriteAllText(fullPath, content, new UTF8Encoding(false));\n    }\n    catch (Exception ex) { throw new Exception($\"写入文件失败: {ex.Message}\"); }\n}\n\n// after (no rewrap; create parent dir if needed after sandbox check)\npublic void WriteFile(string relativePath, string content)\n{\n    var fullPath = Path.Combine(_allowedDirectory, relativePath);\n    if (!IsPathAllowed(fullPath)) throw new UnauthorizedAccessException($\"访问路径 '{relativePath}' 被拒绝\");\n    var dir = Path.GetDirectoryName(fullPath);\n    if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir);\n    File.WriteAllText(fullPath, content, new UTF8Encoding(false));\n}","handlingStrategy":"try-catch","validationCode":"// Ensure parent dir exists (currently commented out) after the sandbox check passes\nvar dir = Path.GetDirectoryName(fullPath);\nif (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir);","typeGuard":null,"tryCatchPattern":"// Remove the catch-all; let UnauthorizedAccessException / IOException propagate.\n// If wrapping is unavoidable:\ncatch (Exception ex)\n{\n    throw new FileAccessBridgeException(\"写入文件失败\", ex);\n}","preventionTips":["Do not catch-all and rewrap — preserve the original exception type.","Uncomment Directory.CreateDirectory so missing parent dirs don't fail writes (after sandbox check).","Log the full exception for disk-full / locked-file diagnosis."],"tags":["exception-handling","anti-pattern","webview","filesystem","catch-all"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}