{"record":{"id":"384f9dd9fb81918e","repo":"dotnet/maui","slug":"the-streams-can-t-be-read-for-comparison","errorCode":null,"errorMessage":"The streams can't be read for comparison","messagePattern":"The streams can't be read for comparison","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/Utilities.cs","lineNumber":166,"sourceCode":"\t\t\treturn (short)(i & 0xFFFF);\n\t\t}\n\n\t\t[SuppressMessage(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n\t\t[SuppressMessage(\"Microsoft.Security\", \"CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands\")]\n\t\tpublic static bool AreStreamsEqual(Stream left, Stream right)\n\t\t{\n\t\t\tif (null == left)\n\t\t\t{\n\t\t\t\treturn right == null;\n\t\t\t}\n\t\t\tif (null == right)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (!left.CanRead || !right.CanRead)\n\t\t\t{\n\t\t\t\tthrow new NotSupportedException(\"The streams can't be read for comparison\");\n\t\t\t}\n\n\t\t\tif (left.Length != right.Length)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar length = (int)left.Length;\n\n\t\t\t// seek to beginning\n\t\t\tleft.Position = 0;\n\t\t\tright.Position = 0;\n\n\t\t\t// total bytes read\n\t\t\tint totalReadLeft = 0;\n\t\t\tint totalReadRight = 0;\n\n\t\t\t// bytes read on this iteration","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/Utilities.cs#L148-L184","documentation":"The AreStreamsEqual utility compares two streams byte-for-byte but first checks that both CanRead. If either stream cannot be read, it throws NotSupportedException because the comparison is impossible. This is a precondition guard, not a recoverable runtime fault.","triggerScenarios":"Calling Utilities.AreStreamsEqual(left, right) where left.CanRead or right.CanRead is false — e.g. passing a write-only FileStream or a closed stream whose CanRead has become false.","commonSituations":"Comparing a stream that was opened with write-only access; passing a stream that was already disposed (some implementations report CanRead=false after Close); comparing against a network stream whose read side has been shut down.","solutions":["Verify left.CanRead && right.CanRead before calling AreStreamsEqual.","Open file streams with FileAccess.Read or ReadWrite when they will be compared.","If comparing data, copy both streams into MemoryStreams first if read access is uncertain."],"exampleFix":"// before\nbool same = Utilities.AreStreamsEqual(left, right);\n\n// after\nif (!left.CanRead || !right.CanRead)\n{\n    throw new InvalidOperationException(\"Both streams must be readable for comparison.\");\n}\nbool same = Utilities.AreStreamsEqual(left, right);","handlingStrategy":"validation","validationCode":"// Before comparing streams\nif (left == null || right == null)\n{\n    // null comparison is valid in AreStreamsEqual (null == null is true)\n}\nif (left != null && right != null && (!left.CanRead || !right.CanRead))\n{\n    throw new InvalidOperationException(\"Both streams must be readable for comparison.\");\n}\nbool equal = Utilities.AreStreamsEqual(left, right);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Open FileStreams with at least read access when they will be compared.","Do not compare disposed streams — CanRead may return false after Close.","Copy untrusted streams into MemoryStreams before comparison if readability is uncertain."],"tags":["stream","io","validation","comparison"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}