{"record":{"id":"e2b5a30df56f7cf2","repo":"wavetermdev/waveterm","slug":"command-packets-may-not-have-error-set","errorCode":null,"errorMessage":"command packets may not have error set","messagePattern":"command packets may not have error set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrpc.go","lineNumber":166,"sourceCode":"\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\")\n\t\t}\n\t\tif r.Timeout != 0 {\n\t\t\treturn fmt.Errorf(\"non-command request packets may not have timeout set\")\n\t\t}\n\t\treturn nil\n\t}\n\tif r.ResId != \"\" {\n\t\tif r.Command != \"\" {\n\t\t\treturn fmt.Errorf(\"response packets may not have command set\")","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrpc.go#L148-L184","documentation":"Packet validation error: COMMAND packets must not carry an error. Errors are only meaningful on response packets; a command with error set is malformed and rejected.","triggerScenarios":"Calling Validate on an RpcMessage with Command set and Error non-empty.","commonSituations":"A handler that tries to return an error by mutating the request message instead of sending a response; error-propagation helpers that set both Command and Error on one struct.","solutions":["Send a response packet with ResId and Error set instead of attaching Error to the command","Clear Error when sending the command","Use the Rpc error-return path in the handler signature rather than hand-building error messages"],"exampleFix":"// before\nmsg := wshutil.RpcMessage{Command: \"job.start\", Error: \"no space\"}\n// after\nresp := wshutil.RpcMessage{ResId: reqId, Error: \"no space\"}","handlingStrategy":"validation","validationCode":"if msg.Command != \"\" && msg.Error != \"\" {\n\treturn fmt.Errorf(\"send errors on response packets, not commands\")\n}\nif err := msg.Validate(); err != nil { return err }","typeGuard":"func isCleanCommand(msg wshutil.RpcMessage) bool {\n\treturn msg.Command == \"\" || (msg.Error == \"\" && msg.ResId == \"\" && msg.DataType == \"\")\n}","tryCatchPattern":"if err := msg.Validate(); err != nil {\n\treturn fmt.Errorf(\"command has error field: %w\", err)\n}","preventionTips":["Return errors via the RPC handler's error return, not by editing the request","Keep request structs immutable through the call path","Review middleware that copies message fields"],"tags":["wsh","rpc","validation","error-handling"],"backgroundTag":"invalid-rpc-packet","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}