Summary
send_async() performs two separate awaited writes (JSON body, then newline). If the first succeeds but the second fails or the task is cancelled between awaits, the client receives a JSON body with no trailing newline — an incomplete NDJSON frame that breaks the parser.
Details
- The sync transport uses a single
writeln! on a BufWriter<StdoutLock>, so it doesn't have this problem.
- Fix: serialize to
String, push '\n', and call write_all once. Treat any write error as fatal.
- Scope:
transport_async.rs::send_async() only.
Summary
send_async()performs two separate awaited writes (JSON body, then newline). If the first succeeds but the second fails or the task is cancelled between awaits, the client receives a JSON body with no trailing newline — an incomplete NDJSON frame that breaks the parser.Details
writeln!on aBufWriter<StdoutLock>, so it doesn't have this problem.String, push'\n', and callwrite_allonce. Treat any write error as fatal.transport_async.rs::send_async()only.