{"record":{"id":"8bc1bdad4e1631f5","repo":"wavetermdev/waveterm","slug":"invalid-packet-must-have-command-reqid-or-resid","errorCode":null,"errorMessage":"invalid packet: must have command, reqid, or resid set","messagePattern":"invalid packet: must have command, reqid, or resid set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrpc.go","lineNumber":194,"sourceCode":"\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\")\n\t\t}\n\t\tif r.ReqId == \"\" {\n\t\t\treturn fmt.Errorf(\"response packets must have reqid set\")\n\t\t}\n\t\tif r.Timeout != 0 {\n\t\t\treturn fmt.Errorf(\"response packets may not have timeout set\")\n\t\t}\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"invalid packet: must have command, reqid, or resid set\")\n}\n\ntype rpcData struct {\n\tCommand string\n\tRoute   string\n\tResCh   chan *RpcMessage\n\tHandler *RpcRequestHandler\n}\n\nfunc validateServerImpl(serverImpl ServerImpl) {\n\tif serverImpl == nil {\n\t\treturn\n\t}\n\tserverType := reflect.TypeOf(serverImpl)\n\tif serverType.Kind() != reflect.Pointer && serverType.Elem().Kind() != reflect.Struct {\n\t\tpanic(fmt.Sprintf(\"serverImpl must be a pointer to struct, got %v\", serverType))\n\t}\n}","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrpc.go#L176-L212","documentation":"Every RpcMessage must be classifiable as a request (Command set), a response (ResId set), or otherwise carry ReqId. Validate() returns this error when Command, ReqId, and ResId are all empty — the packet has no routing identity and cannot be dispatched.","triggerScenarios":"Sending a zero-value RpcMessage, an empty payload, or a message whose meaningful fields live only in nested data without any of the three required fields set.","commonSituations":"Uninitialized structs passed to the writer; JSON round-trips that dropped fields due to schema mismatch between versions; generic forwarding code that passes through empty envelopes.","solutions":["Populate Command (plus ReqId) for requests or ResId/ReqId for responses before sending.","Check that the message actually got serialized/deserialized with the expected fields (field-name/tag mismatches).","Guard send paths with Validate() and skip/log packets that fail rather than pushing them onto OutputCh.","Upgrade both ends of the connection to matching wshutil versions to avoid field-shape drift."],"exampleFix":"// before\nw.OutputCh <- &wshutil.WshRpcDataStream{MsgBytes: mustJSON(wshrpc.RpcMessage{})}\n// after\nw.OutputCh <- &wshutil.WshRpcDataStream{MsgBytes: mustJSON(wshrpc.RpcMessage{Command: \"waveclient:get\", ReqId: genId()})}","handlingStrategy":"validation","validationCode":"func checkPacketIdentity(m wshrpc.RpcMessage) error {\n    if m.Command == \"\" && m.ReqId == \"\" && m.ResId == \"\" {\n        return fmt.Errorf(\"packet has no command/reqid/resid\")\n    }\n    return nil\n}","typeGuard":"func hasIdentity(m wshrpc.RpcMessage) bool {\n    return m.Command != \"\" || m.ReqId != \"\" || m.ResId != \"\"\n}","tryCatchPattern":null,"preventionTips":["Never send zero-value RpcMessage structs.","Call Validate() on packets before enqueueing them.","Keep both wshutil endpoints on the same version to avoid serialization field drift.","Log raw marshaled packets when debugging dispatch failures."],"tags":["rpc","protocol-validation","invalid-packet"],"backgroundTag":"rpc-packet-validation-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}