dotnet/yarp · error · Exception
Read {read} bytes, expected 1.
Error message
Read {read} bytes, expected 1. What it means
Asserted inside RawUpgradeScenario's echo loop for every byte except the final goodbye (i == 255). After writing one byte it expects exactly one byte echoed back; if ReadAsync returns a count other than 1 it throws Exception with the actual count, indicating the upgraded stream is not doing a clean one-byte echo.
Source
Thrown at testassets/TestClient/Scenarios/RawUpgradeScenario.cs:61
for (var i = 0; i <= 255; i++)
{
buffer[0] = (byte)i;
await rawStream.WriteAsync(buffer, cancellation);
var read = await rawStream.ReadAsync(buffer, cancellation);
if (i == 255)
{
if (read != 0)
{
throw new Exception($"Read {read} bytes, expected 0 after sending Goodbye.");
}
Console.WriteLine();
}
else
{
if (read != 1)
{
throw new Exception($"Read {read} bytes, expected 1.");
}
if (buffer[0] != i)
{
throw new Exception($"Received {buffer[0]}, expected {i}.");
}
Console.Write(".");
}
}
Console.WriteLine($"256 ping/pong's completed in {stopwatch.ElapsedMilliseconds} ms.");
}
}
View on GitHub (pinned to bd11867bee)
Solutions
- Use the matching test backend that performs a strict one-byte echo.
- Ensure no intermediary (proxy, TLS terminator) alters the upgraded byte stream.
- If you control the backend, echo exactly the bytes received per read.
- Inspect where in the 0..255 range the failure occurs (printed dots show progress) to spot partial connectivity.
Defensive patterns
Strategy: try-catch
Try / catch
try { await RawUpgradeScenario.RunAsync(client, args, cancellation); }
catch (Exception ex) when (ex.Message.Contains("expected 1")) {
Console.Error.WriteLine("Upgraded stream did not echo one byte per write; check backend and intermediaries.");
return 1;
} Prevention
- Use the strict one-byte echo backend the scenario expects.
- Remove intermediaries that coalesce or fragment the upgraded stream.
- Watch the printed dots to see how far the loop got before failing.
When it happens
Trigger: Running RawUpgradeScenario against a raw-upgrade endpoint that buffers, fragments, or drops bytes rather than echoing exactly one byte per write.
Common situations: Backend that echoes in chunks; a proxy in front that coalesces or splits frames; TCP-level buffering returning 0 (closed) mid-loop; the stream returning more than one byte because the backend sent ahead.
Related errors
- Expected status 101 Switching Protocols!
- Read {read} bytes, expected 0 after sending Goodbye.
- Received {buffer[0]}, expected {i}.
- Expected status 409 Conflict!
- Expected to receive a text message, got '{message.MessageTyp
AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13).
Data as JSON: /api/errors/0a10813abfba8d41.
Report an issue: GitHub.