wavetermdev/waveterm · error
response packets may not have timeout set
Error message
response packets may not have timeout set
What it means
Packet validation error: RESPONSE packets must not carry a timeout. Timeouts are specified by the requester on the command; echoing a timeout on a response is a protocol violation and the packet is rejected.
Source
Thrown at pkg/wshutil/wshrpc.go:190
}
if r.ReqId != "" {
if r.ResId == "" {
return fmt.Errorf("request packets must have resid set")
}
if r.Timeout != 0 {
return fmt.Errorf("non-command request packets may not have timeout set")
}
return nil
}
if r.ResId != "" {
if r.Command != "" {
return fmt.Errorf("response packets may not have command set")
}
if r.ReqId == "" {
return fmt.Errorf("response packets must have reqid set")
}
if r.Timeout != 0 {
return fmt.Errorf("response packets may not have timeout set")
}
return nil
}
return fmt.Errorf("invalid packet: must have command, reqid, or resid set")
}
type rpcData struct {
Command string
Route string
ResCh chan *RpcMessage
Handler *RpcRequestHandler
}
func validateServerImpl(serverImpl ServerImpl) {
if serverImpl == nil {
return
}
serverType := reflect.TypeOf(serverImpl)View on GitHub (pinned to a4447c1563)
Solutions
- Zero out Timeout on any packet carrying ResId before validating/sending.
- Build responses from scratch (only ResId, ReqId, data) instead of mutating request messages.
- Use the handler-based response APIs (SendResponse/SendComplexRequest) so field ownership is explicit.
Example fix
// before
resp := reqMsg // carries Timeout
resp.ResId = "res-1"
// after
resp := wshrpc.RpcMessage{ResId: "res-1", ReqId: reqMsg.ReqId} Defensive patterns
Strategy: validation
Validate before calling
func checkResNoTimeout(m wshrpc.RpcMessage) error {
if m.ResId != "" && m.Timeout != 0 {
return fmt.Errorf("response packet has timeout set")
}
return nil
} Type guard
func isCleanResponse(m wshrpc.RpcMessage) bool {
return m.ResId != "" && m.Command == "" && m.Timeout == 0 && m.ReqId != ""
} Prevention
- Build response packets from scratch rather than mutating request packets.
- Keep Timeout only in request options (RpcOpts), never in response messages.
- Sanitize packets in any forwarding/middleware layer before re-emitting them.
When it happens
Trigger: Building or copying an RpcMessage where Timeout (or the opts timeout carried into the message) survives from a request into a response packet with ResId set.
Common situations: Cloning a request message and mutating it into a response without clearing Timeout; middleware that forwards all fields of an incoming packet back out; serialization of stale cached messages.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- failed to list workspaces: %v
- failed to list blocks from all %d workspace(s)
- reinstalling connection: %w
- disconnecting %q error: %w
- ensuring connection: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/ffa4481f6245b0d8.
Report an issue: GitHub.