kovidgoyal/kitty · error
Did not receive expected streaming response
Error message
Did not receive expected streaming response
What it means
simple_socket_io expected the peer's reply to look like a streaming response (validated by is_stream_response), but the bytes read from the connection did not match that format. This means the connection succeeded and data arrived, but the remote is not speaking the expected streaming protocol (e.g. it replied with a plain/error response instead).
Source
Thrown at tools/cmd/at/socket_io.go:151
return
}
if len(chunk) == 0 {
break
}
err = write_many_to_conn(conn, []byte(cmd_escape_code_prefix), chunk, []byte(cmd_escape_code_suffix))
if err != nil {
return
}
if !first_escape_code_sent {
first_escape_code_sent = true
if wants_streaming {
var streaming_response []byte
streaming_response, err = r.read_response_from_conn(conn, io_data.timeout)
if err != nil {
return
}
if !is_stream_response(streaming_response) {
err = fmt.Errorf("Did not receive expected streaming response")
return
}
}
}
}
if io_data.rc.NoResponse {
return
}
return r.read_response_from_conn(conn, io_data.timeout)
}
func do_socket_io(io_data *rc_io_data) (serialized_response []byte, err error) {
var conn net.Conn
if global_options.to_network == "fd" {
fd, _ := strconv.Atoi(global_options.to_address)
if err != nil {
return nil, err
}View on GitHub (pinned to 6d5d0c4406)
Solutions
- Verify the remote address/network actually serves the expected streaming protocol (test with the same tool version on both ends)
- Check that the peer process is the correct version and configured for streaming responses
- Capture the bytes returned (log streaming_response) to see what the peer actually sent — often an error message revealing the mismatch
- If a proxy sits in the path, bypass it or configure it to pass the stream through unmodified
Example fix
# before at --to tcp:host:9000 --expect-stream # after: point at the actual streaming endpoint and matching protocol version at --to tcp:host:9001 --expect-stream # port of the real streaming daemon
Defensive patterns
Strategy: validation
Validate before calling
// Before requesting streaming mode, probe the peer with a tiny request
// and confirm the reply matches the streaming protocol.
resp, err := probe(toAddr)
if err == nil && !isStreamResponse(resp) {
log.Fatalf("peer at %s does not speak the streaming protocol; check address/version", toAddr)
} Try / catch
// In Go: inspect the error text at the call site
if err != nil && strings.Contains(err.Error(), "Did not receive expected streaming response") {
// peer reachable but wrong protocol: don't retry, alert on config
log.Printf("protocol mismatch with %s — verify server version", addr)
return err
} Prevention
- Pin client and server to matching protocol versions
- Add a startup handshake/protocol check before relying on streaming replies
- Log raw responses when validation fails to speed up diagnosis
When it happens
Trigger: Calling the at tool with streaming mode requested (io_data requests a stream response) against a listener that answers with a non-streaming payload, closes early, or sends a protocol error frame, so is_stream_response(streaming_response) returns false after a successful read_response_from_conn.
Common situations: Pointing --to at the wrong port/service (e.g. an HTTP server instead of the expected streaming daemon), a version mismatch between client and server protocol, or a proxy that mangles/truncates the streamed reply.
Related errors
- Failed to connect to %s:%s with error: %w
- output slice too small: need at least %d, got %d
- Too much data being sent
- No stream_id in rc payload
- Too much piped data
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/157abbe201d1de78.
Report an issue: GitHub.