wavetermdev/waveterm · error

response packets must have reqid set

Error message

response packets must have reqid set

What it means

A response packet (ResId set) must carry the ReqId of the original request so the caller's pending request can be correlated and resolved. Validate() rejects responses lacking ReqId because they cannot be routed back to any awaiting request.

Source

Thrown at pkg/wshutil/wshrpc.go:187

			return fmt.Errorf("command packets may not have datatype set")
		}
		return nil
	}
	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 {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set ReqId to the request id from the incoming request before sending the response.
  2. Reply via RpcResponseHandler.SendResponse, which fills ReqId automatically from the handler.
  3. If the packet is not a response, remove ResId; a pure command packet needs Command/ReqId instead.
  4. Log and inspect the raw packet (EnableRpcDebug) to confirm which fields are actually populated.

Example fix

// before
msg := wshrpc.RpcMessage{ResId: "res-1"}
// after
msg := wshrpc.RpcMessage{ResId: "res-1", ReqId: origReqId}
Defensive patterns

Strategy: validation

Validate before calling

func checkResReqId(m wshrpc.RpcMessage) error {
    if m.ResId != "" && m.ReqId == "" {
        return fmt.Errorf("response missing reqid")
    }
    return nil
}

Type guard

func isRoutableResponse(m wshrpc.RpcMessage) bool {
    return m.ResId != "" && m.ReqId != ""
}

Prevention

When it happens

Trigger: Constructing an RpcMessage with ResId but leaving ReqId empty — e.g., building a reply manually without reading the request's ReqId, or a response path that drops the correlation id.

Common situations: Hand-rolled response messages in tooling or tests; losing the request id when forwarding packets between connections; correlating responses across restarted connections.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/c017de44fe9784a9. Report an issue: GitHub.