{"record":{"id":"204f799df3a30cad","repo":"babalae/better-genshin-impact","slug":"ex-message-204f79","errorCode":null,"errorMessage":"列出项目失败: {ex.Message}","messagePattern":"列出项目失败: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Script/WebView/FileAccessBridge.cs","lineNumber":179,"sourceCode":"            foreach (var file in files)\n            {\n                var relativeName = Path.GetRelativePath(_allowedDirectory, file);\n                var fileInfo = new FileInfo(file);\n                items.Add(new FileSystemItem\n                {\n                    Name = Path.GetFileName(file),\n                    RelativePath = relativeName,\n                    IsDirectory = false,\n                    Size = fileInfo.Length,\n                    LastModified = fileInfo.LastWriteTime\n                });\n            }\n\n            return JsonConvert.SerializeObject(items);\n        }\n        catch (Exception ex)\n        {\n            throw new Exception($\"列出项目失败: {ex.Message}\");\n        }\n    }\n}","sourceCodeStart":161,"sourceCodeEnd":182,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Script/WebView/FileAccessBridge.cs#L161-L182","documentation":"A catch-all wrapper thrown by ListItems: every exception inside the method is re-thrown as a plain System.Exception with prefix '列出项目失败: '. The original exception type (UnauthorizedAccessException, IOException, UnauthorizedAccessException, etc.) is lost at the call boundary, so callers only see a message string. The inner exception is not preserved (no 'ex' passed to the constructor).","triggerScenarios":"Any failure during directory enumeration: the UnauthorizedAccessException from the path guard (error 140), Directory.GetDirectories/GetFiles throwing UnauthorizedAccessException for ACL-protected children, IOException on a dropped network share, or ObjectDisposedException on the underlying stream.","commonSituations":"Listing a directory that contains a locked/access-denied subfolder; antivirus intercepting file enumeration; the allowed directory sitting on a disconnected removable drive; the path guard rejecting a path and that UnauthorizedAccessException being flattened into this message.","solutions":["Inspect the message suffix after '列出项目失败: ' to recover the original cause; for path-guard rejections, fix the relative path (see error 140).","For ACL/IO errors, run the host process with sufficient privileges or exclude the denied subdirectory.","Have callers parse on ': ' and treat '访问路径...被拒绝' as a security rejection vs other text as an I/O error.","Consider patching ListItems to preserve the inner exception ('new Exception(msg, ex)') so callers can catch by type."],"exampleFix":"// before\ncatch (Exception ex)\n{\n    throw new Exception($\"列出项目失败: {ex.Message}\");\n}\n// after - preserve inner for typed handling\ncatch (Exception ex)\n{\n    throw new Exception($\"列出项目失败: {ex.Message}\", ex);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    var json = bridge.ListItems(rel);\n}\ncatch (Exception ex) when (ex.Message.StartsWith(\"列出项目失败:\"))\n{\n    var inner = ex.Message.Substring(\"列出项目失败:\".Length).Trim();\n    if (inner.Contains(\"被拒绝\")) HandleSecurityRejection(rel);\n    else HandleIoError(inner);\n}","preventionTips":["Parse the message suffix to branch on the original cause.","Patch ListItems to preserve the inner exception for typed catches.","Log the full message for post-mortem since the type is lost."],"tags":["error-handling","webview","io","anti-pattern"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}