{"record":{"id":"f68ee2014922ed4b","repo":"dotnet/BenchmarkDotNet","slug":"tried-to-read-size-bytes-for-currentmethod-sign","errorCode":null,"errorMessage":"Tried to read {size} bytes for {currentMethod.Signature}, got only {totalBytesRead}","messagePattern":"Tried to read (.+?) bytes for (.+?), got only (.+?)","errorType":"exception","errorClass":"EndOfStreamException","httpStatus":null,"severity":"error","filePath":"src/BenchmarkDotNet/Disassemblers/ClrMdDisassembler.cs","lineNumber":222,"sourceCode":"                Name = method.Signature ?? \"\",\n                NativeCode = method.NativeCode\n            };\n        }\n\n        private IEnumerable<Asm> Decode(ILToNativeMap map, State state, int depth, ClrMethod currentMethod, DisassemblySyntax syntax)\n        {\n            ulong startAddress = map.StartAddress;\n            uint size = (uint)(map.EndAddress - map.StartAddress);\n\n            byte[] code = new byte[size];\n\n            int totalBytesRead = 0;\n            do\n            {\n                int bytesRead = state.Runtime.DataTarget.DataReader.Read(startAddress + (ulong)totalBytesRead, new Span<byte>(code, totalBytesRead, (int)size - totalBytesRead));\n                if (bytesRead <= 0)\n                {\n                    throw new EndOfStreamException($\"Tried to read {size} bytes for {currentMethod.Signature}, got only {totalBytesRead}\");\n                }\n                totalBytesRead += bytesRead;\n            } while (totalBytesRead != size);\n\n            return Decode(code, startAddress, state, depth, currentMethod, syntax);\n        }\n\n        protected abstract IEnumerable<Asm> Decode(byte[] code, ulong startAddress, State state, int depth, ClrMethod currentMethod, DisassemblySyntax syntax);\n\n        private static ILToNativeMap[] GetCompleteNativeMap(ClrMethod method, ClrRuntime runtime)\n        {\n            // it's better to use one single map rather than few small ones\n            // it's simply easier to get next instruction when decoding ;)\n\n            var hotColdInfo = method.HotColdInfo;\n            if (hotColdInfo.HotSize > 0 && hotColdInfo.HotStart > 0)\n            {\n                return hotColdInfo.ColdSize <= 0","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/dotnet/BenchmarkDotNet/blob/b515068b61ad1c9c9aa938b8ece4af1e7d6d85a3/src/BenchmarkDotNet/Disassemblers/ClrMdDisassembler.cs#L204-L240","documentation":"While reading a method's native bytes for disassembly, the code loops calling DataReader.Read into a buffer sized to map.EndAddress - map.StartAddress. If a Read call returns <= 0 before the full `size` bytes are obtained, EndOfStreamException is thrown. This indicates the target process's memory region could not be fully read: the process exited, the JIT freed/moved the code, or the address range was unmapped mid-read.","triggerScenarios":"Disassembling a short-lived or JIT-torn method, reading while the benchmark process is terminating, GC/JIT moving the code after the map was computed, or attaching to a process whose memory is partially paged out/protected.","commonSituations":"Long-running benchmark suites where the target process exits before disassembly completes, Tiered JIT recompiling a method mid-read, attach-snapshot races, or low-memory/over-committed systems.","solutions":["Retry the disassembly once the target process is stable; transient reads often succeed on a clean snapshot (use CreateSnapshotAndAttach to reduce races).","Disable Tiered JIT / use a fixed tier so methods are not recompiled during the read (set DOTNET_TieredCompilation=0 in the benchmark job environment).","Filter the disassembly to a stable set of methods and avoid disassembling during teardown.","Ensure the process stays alive for the duration of the read; increase process liveness / run disassembly before the process exits."],"exampleFix":"// before - tiered JIT can move code mid-read\nvar job = Job.Default.WithEnvironmentVariable(\"DOTNET_TieredCompilation\", \"1\");\n\n// after - disable tiering so the native map stays valid\nvar job = Job.Default.WithEnvironmentVariable(\"DOTNET_TieredCompilation\", \"0\");","handlingStrategy":"retry","validationCode":"if (process.HasExited)\n    throw new InvalidOperationException(\"Cannot disassemble: target process has exited.\");\n// optionally pre-check map validity before reading","typeGuard":"static bool ProcessAliveForDisasm(Process p) => !p.HasExited;","tryCatchPattern":"for (int attempt = 0; attempt < 3; attempt++)\n{\n    try { return disassembler.AttachAndDisassemble(args); }\n    catch (EndOfStreamException) when (attempt < 2)\n    {\n        // back off briefly and re-snapshot the process before retrying\n    }\n}\nthrow;","preventionTips":["Disable Tiered JIT (DOTNET_TieredCompilation=0) so methods are not recompiled mid-read.","Use a process snapshot (CreateSnapshotAndAttach) to reduce JIT/GC races.","Keep the benchmark process alive until disassembly completes; avoid teardown races.","Filter disassembly to stable, long-lived methods when possible."],"tags":["disassembler","memory-read","transient","clrmd","endofstream","jit"],"backgroundTag":null,"analyzedSha":"b515068b61ad1c9c9aa938b8ece4af1e7d6d85a3","analyzedAt":"2026-08-13T19:12:24.196Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}