{"record":{"id":"fdbe5ec0650a37dd","repo":"wavetermdev/waveterm","slug":"error-marshalling-message-to-json-w","errorCode":null,"errorMessage":"error marshalling message to json: %w","messagePattern":"error marshalling message to json: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshutil.go","lineNumber":121,"sourceCode":"\t\tif b < 0x20 || b == 0x7f {\n\t\t\tescSeq[4] = HexChars[b>>4]\n\t\t\tescSeq[5] = HexChars[b&0x0f]\n\t\t\tbuf.Write(escSeq[:])\n\t\t} else {\n\t\t\tbuf.WriteByte(b)\n\t\t}\n\t}\n\tbuf.WriteByte(BEL)\n\treturn buf.Bytes(), nil\n}\n\nfunc EncodeWaveOSCMessageEx(oscNum string, msg *RpcMessage) ([]byte, error) {\n\tif msg == nil {\n\t\treturn nil, fmt.Errorf(\"nil message\")\n\t}\n\tbarr, err := json.Marshal(msg)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error marshalling message to json: %w\", err)\n\t}\n\treturn EncodeWaveOSCBytes(oscNum, barr)\n}\n\nvar shutdownOnce sync.Once\n\nfunc DoShutdown(reason string, exitCode int, quiet bool) {\n\tshutdownOnce.Do(func() {\n\t\tdefer os.Exit(exitCode)\n\t\tif !quiet && reason != \"\" {\n\t\t\tlog.Printf(\"shutting down: %s\\n\", reason)\n\t\t}\n\t})\n}\n\nfunc SetupPacketRpcClient(input io.Reader, output io.Writer, serverImpl ServerImpl, debugStr string) (*WshRpc, chan []byte) {\n\tmessageCh := make(chan baseds.RpcInputChType, DefaultInputChSize)\n\toutputCh := make(chan []byte, DefaultOutputChSize)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshutil.go#L103-L139","documentation":"EncodeWaveOSCMessageEx marshals the RpcMessage to JSON before OSC encoding. This error wraps a json.Marshal failure, which happens when the message contains data that cannot be serialized — most commonly unsupported types (channels, funcs) placed in the Data field, or a custom MarshalJSON that errors.","triggerScenarios":"json.Marshal(msg) fails for an *RpcMessage whose payload (e.g. Data as any) holds unserializable values like func, chan, cycle references, or a type with a failing MarshalJSON.","commonSituations":"Storing a callback or Go-specific value in the loosely-typed Data field; cyclic object graphs; incompatible types after a struct refactor.","solutions":["Inspect the wrapped %w error to find the offending field/type.","Ensure Data contains only JSON-safe values (maps, slices, strings, numbers, bools).","Add a serialization smoke test for message builders.","Marshal the payload yourself earlier to surface the bad field with better context."],"exampleFix":"// before\nmsg := &RpcMessage{Data: func() {}} // unserializable\nbarr, err := EncodeWaveOSCMessageEx(\"1337;\", msg)\n// after\nmsg := &RpcMessage{Data: map[string]any{\"result\": serializedResult}}\nbarr, err := EncodeWaveOSCMessageEx(\"1337;\", msg)","handlingStrategy":"validation","validationCode":"if _, err := json.Marshal(msg); err != nil {\n    return fmt.Errorf(\"message not JSON-serializable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if _, err := EncodeWaveOSCMessageEx(oscNum, msg); err != nil {\n    var uerr *json.UnsupportedTypeError\n    if errors.As(err, &uerr) {\n        log.Printf(\"unsupported field type: %v\", uerr.Value)\n    }\n    return err\n}","preventionTips":["Keep RpcMessage.Data limited to JSON-safe types","Add marshal smoke tests for all message builders","Avoid storing funcs/chans/cycles in message payloads"],"tags":["go","json","serialization"],"backgroundTag":"json-serialization-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}