{"record":{"id":"980c72eed197eb58","repo":"wavetermdev/waveterm","slug":"cancel-packets-may-not-have-data-set","errorCode":null,"errorMessage":"cancel packets may not have data set","messagePattern":"cancel packets may not have data set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrpc.go","lineNumber":157,"sourceCode":"}\n\nfunc (r *RpcMessage) IsRpcRequest() bool {\n\treturn r.Command != \"\" || r.ReqId != \"\"\n}\n\nfunc (r *RpcMessage) Validate() error {\n\tif r.ReqId != \"\" && r.ResId != \"\" {\n\t\treturn fmt.Errorf(\"request packets may not have both reqid and resid set\")\n\t}\n\tif r.Cancel {\n\t\tif r.Command != \"\" {\n\t\t\treturn fmt.Errorf(\"cancel packets may not have command set\")\n\t\t}\n\t\tif r.ReqId == \"\" && r.ResId == \"\" {\n\t\t\treturn fmt.Errorf(\"cancel packets must have reqid or resid set\")\n\t\t}\n\t\tif r.Data != nil {\n\t\t\treturn fmt.Errorf(\"cancel packets may not have data set\")\n\t\t}\n\t\treturn nil\n\t}\n\tif r.Command != \"\" {\n\t\tif r.ResId != \"\" {\n\t\t\treturn fmt.Errorf(\"command packets may not have resid set\")\n\t\t}\n\t\tif r.Error != \"\" {\n\t\t\treturn fmt.Errorf(\"command packets may not have error set\")\n\t\t}\n\t\tif r.DataType != \"\" {\n\t\t\treturn fmt.Errorf(\"command packets may not have datatype set\")\n\t\t}\n\t\treturn nil\n\t}\n\tif r.ReqId != \"\" {\n\t\tif r.ResId == \"\" {\n\t\t\treturn fmt.Errorf(\"request packets must have resid set\")","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrpc.go#L139-L175","documentation":"Packet validation error: CANCEL packets must not carry a data payload. A cancel only references the request being cancelled (by resid); attaching data is a protocol violation and the packet is rejected.","triggerScenarios":"Calling Validate on an RpcMessage with Cancel=true, valid ReqId/ResId, and Data != nil.","commonSituations":"Reusing a request message struct (which had a Data payload) and just setting Cancel=true; serialization pipelines that always populate Data.","solutions":["Set Data = nil on the cancel message","Build the cancel packet from scratch instead of mutating the original request","Ensure generic encode helpers do not attach Data to control packets"],"exampleFix":"// before\nmsg := wshutil.RpcMessage{Cancel: true, ReqId: origId, Data: payload}\n// after\nmsg := wshutil.RpcMessage{Cancel: true, ReqId: origId, Data: nil}","handlingStrategy":"validation","validationCode":"if msg.Cancel {\n\tmsg.Data = nil\n}\nif err := msg.Validate(); err != nil { return err }","typeGuard":"func cancelHasNoData(msg wshutil.RpcMessage) bool {\n\treturn !msg.Cancel || msg.Data == nil\n}","tryCatchPattern":"if err := msg.Validate(); err != nil {\n\treturn fmt.Errorf(\"cancel packet has data: %w\", err)\n}","preventionTips":["Construct cancel packets from scratch, not by mutating requests","Avoid generic encode helpers that always attach Data","Add a unit test that round-trips a cancel packet through Validate"],"tags":["wsh","rpc","validation","cancel"],"backgroundTag":"invalid-rpc-packet","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}