{"record":{"id":"2cd52095e4da18d2","repo":"chenhg5/cc-connect","slug":"wps-agentspace-marshal-frame-w","errorCode":null,"errorMessage":"wps-agentspace: marshal frame: %w","messagePattern":"wps-agentspace: marshal frame: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wps-agentspace/wpsagentspace.go","lineNumber":655,"sourceCode":"\t\tDeviceName: p.deviceName,\n\t\tTimestamp:  time.Now().UnixMilli(),\n\t})\n}\n\n// writeJSON sends a JSON frame through the write channel.\nfunc (p *Platform) writeJSON(event string, data any) error {\n\tframe := wsFrame{\n\t\tEvent: event,\n\t}\n\tjsonData, err := json.Marshal(data)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"wps-agentspace: marshal: %w\", err)\n\t}\n\tframe.Data = jsonData\n\n\traw, err := json.Marshal(frame)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"wps-agentspace: marshal frame: %w\", err)\n\t}\n\n\tselect {\n\tcase p.writeCh <- raw:\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"wps-agentspace: write buffer full\")\n\t}\n}\n\n// writeLoop serializes all WebSocket writes.\nfunc (p *Platform) writeLoop(conn *websocket.Conn) {\n\tfor msg := range p.writeCh {\n\t\tif p.stopped.Load() {\n\t\t\treturn\n\t\t}\n\t\t// msg is already JSON-encoded bytes from writeJSON\n\t\tif err := conn.WriteMessage(websocket.TextMessage, msg.([]byte)); err != nil {","sourceCodeStart":637,"sourceCodeEnd":673,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wps-agentspace/wpsagentspace.go#L637-L673","documentation":"writeJSON marshals the outer wsFrame envelope to JSON; a failure here means the frame struct itself cannot be serialized. Since wsFrame is fixed (Event string, Data []byte), this is nearly impossible in normal operation and signals a code-level change to the frame struct or a corrupted Data field.","triggerScenarios":"Calling writeJSON (via sendInit, heartbeatLoop, handleFrame, sendText, sendTyping) after wsFrame has been modified to include unserializable fields, or Data has been altered.","commonSituations":"A developer adds a field of unsupported type to wsFrame or embeds a struct with cyclic references; production builds then fail on every send.","solutions":["Check recent changes to the wsFrame struct for unserializable fields","Inspect the wrapped inner error for the failing Go path","Revert the struct change or implement MarshalJSON for the new field type"],"exampleFix":"// before\ntype wsFrame struct {\n    Event string\n    Data  []byte\n    Callback func() // unserializable\n}\n// after\ntype wsFrame struct {\n    Event string\n    Data  []byte\n}","handlingStrategy":"validation","validationCode":"func assertFrameSerializable(f wsFrame) error { _, err := json.Marshal(f); return err }","typeGuard":null,"tryCatchPattern":"if err := p.sendText(chatID, text); err != nil { if strings.Contains(err.Error(), \"marshal frame:\") { slog.Error(\"frame serialization failed\", \"err\", err) } }","preventionTips":["Never add unserializable fields to wsFrame","Add a marshaling round-trip test for wsFrame","Use []byte fields only for already-serialized data"],"tags":["websocket","json","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}