henrygd/beszel · error
failed to marshal request
Error message
failed to marshal request: %w
What it means
sendMessage CBOR-marshals the request payload before writing it to the WebSocket. This error is returned when cbor.Marshal fails on the request data, so nothing is sent over the wire.
Solutions
- Log the wrapped cause (%w) to identify the offending value
- Ensure the request payload contains only CBOR-serializable types (primitives, slices, maps, structs with exported fields)
- Send nil or a plain struct/map as the request data
Example fix
// before
req := map[string]any{"cb": make(chan int)} // not CBOR-serializable
rm.SendRequest(ctx, action, req)
// after
req := map[string]any{"action": "status"}
rm.SendRequest(ctx, action, req) Defensive patterns
Strategy: validation
Validate before calling
if err := cbor.Marshal(data); err != nil {
return fmt.Errorf("request payload not CBOR-serializable: %w", err)
} Try / catch
if _, err := rm.SendRequest(ctx, action, data); err != nil {
if strings.Contains(err.Error(), "failed to marshal request") { /* fix payload types */ }
return err
} Prevention
- Send only CBOR-serializable payloads (primitives, maps, slices, exported struct fields)
- Avoid channels, funcs, and cyclic references in request data
- Pre-send smoke-test new payload types with cbor.Marshal in tests
When it happens
Trigger: Passing a request payload containing types cbor.Marshal cannot encode (e.g. channels, funcs, cyclic structures, or unexported fields expected to serialize) to SendRequest.
Common situations: Sending custom structs with unsupported field types or channels; attaching context values or non-serializable objects to the request; a custom CBOR encoder mode rejecting a type.
Related errors
- failed to encode request
- failed to decode response
- failed to send request
- failed to unmarshal generic response data
- HUB_URL environment variable not set
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/442c90df002adccf.
Report an issue: GitHub.
Appendix: source
Thrown at internal/hub/ws/request_manager.go:96
rm.cancelRequest(reqID)
return nil, fmt.Errorf("failed to send request: %w", err)
}
// Start cleanup watcher for timeout/cancellation
go rm.cleanupRequest(req)
return req, nil
}
// sendMessage encodes and sends a message over WebSocket
func (rm *RequestManager) sendMessage(data any) error {
if rm.conn == nil {
return gws.ErrConnClosed
}
bytes, err := cbor.Marshal(data)
if err != nil {
return fmt.Errorf("failed to marshal request: %w", err)
}
return rm.conn.WriteMessage(gws.OpcodeBinary, bytes)
}
// handleResponse processes a single response message
func (rm *RequestManager) handleResponse(message *gws.Message) {
var response common.AgentResponse
if err := cbor.Unmarshal(message.Data.Bytes(), &response); err != nil {
// Legacy response without ID - route to first pending request of any type
rm.routeLegacyResponse(message)
return
}
if response.Id == nil {
rm.routeLegacyResponse(message)
return
}View on GitHub (pinned to b38fb7dafa)