chenhg5/cc-connect · error
wps-agentspace: marshal: %w
Error message
wps-agentspace: marshal: %w
What it means
writeJSON marshals the data payload to JSON before wrapping it in a wsFrame; if json.Marshal fails on the payload it returns this wrapped error. It means the data passed to the WebSocket sender is not JSON-serializable (e.g. channels, funcs, cyclic structures).
Source
Thrown at platform/wps-agentspace/wpsagentspace.go:649
// sendTyping sends a typing indicator.
func (p *Platform) sendTyping(chatID string) {
_ = p.writeJSON("typing", typingData{
ChatID: chatID,
DeviceUUID: p.deviceUuid,
DeviceName: p.deviceName,
Timestamp: time.Now().UnixMilli(),
})
}
// writeJSON sends a JSON frame through the write channel.
func (p *Platform) writeJSON(event string, data any) error {
frame := wsFrame{
Event: event,
}
jsonData, err := json.Marshal(data)
if err != nil {
return fmt.Errorf("wps-agentspace: marshal: %w", err)
}
frame.Data = jsonData
raw, err := json.Marshal(frame)
if err != nil {
return fmt.Errorf("wps-agentspace: marshal frame: %w", err)
}
select {
case p.writeCh <- raw:
return nil
default:
return fmt.Errorf("wps-agentspace: write buffer full")
}
}
// writeLoop serializes all WebSocket writes.
func (p *Platform) writeLoop(conn *websocket.Conn) {View on GitHub (pinned to 4000b2338a)
Solutions
- Inspect the inner error (%w) to find the offending field/type at the given Go path
- Remove or make serializable any func/chan/cyclic fields in the payload struct
- Add a MarshalJSON method to custom types passed into sendText/sendTyping
- Log the data value's type at the call site to identify what fails to marshal
Example fix
// before
p.sendText(chatID, someStructWithChan{done: make(chan struct{})})
// after
payload := struct{ ChatID string `json:"chat_id"`; Text string `json:"text"` }{ChatID: chatID, Text: text}
p.sendText(chatID, payload) Defensive patterns
Strategy: validation
Validate before calling
func isJSONSerializable(v any) error { _, err := json.Marshal(v); return err }
if err := isJSONSerializable(payload); err != nil { log.Fatalf("payload not serializable: %v", err) } Try / catch
if err := p.sendText(chatID, text); err != nil { if strings.Contains(err.Error(), "marshal:") { slog.Error("payload serialization failed", "err", err) } } Prevention
- Keep WebSocket payload structs free of func/chan/cyclic fields
- Add a unit test that marshals every outbound payload type
- Prefer explicit DTO structs over passing arbitrary values
When it happens
Trigger: Calling sendInit, heartbeatLoop, handleFrame, sendText, or sendTyping with a data value containing unsupported types (chan, func, complex) or a cyclic structure passed to writeJSON.
Common situations: A developer extends the platform and passes a custom struct with unserializable fields (e.g. a sync.Mutex is fine, but a func field or circular pointer) into sendText/sendTyping.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- wps-agentspace: marshal frame: %w
- marshal: %w
- codex app-server encode: %w
- marshal: %w
- piSession: marshal command: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/873ff196b21fd393.
Report an issue: GitHub.