gastownhall/beads · error
failed to marshal request: %w
Error message
failed to marshal request: %w
What it means
executeOnce serializes the GraphQLRequest to JSON before sending it. If json.Marshal fails — which for well-formed structs is rare but possible with unsupported values (e.g. channels, funcs, or NaN-like numbers injected via custom types) — the client returns 'failed to marshal request' wrapped around the marshal error before any HTTP call is made.
Source
Thrown at internal/linear/client.go:354
if statusCode == http.StatusUnauthorized && c.AuthMode == AuthModeOAuth {
debug.Logf("oauth: received 401, invalidating token and retrying")
c.TokenManager.Invalidate()
data, _, retryErr := c.executeOnce(ctx, req)
if retryErr != nil {
return nil, retryErr
}
return data, nil
}
return nil, err
}
// executeOnce performs the actual HTTP request loop with rate-limit retries.
// Returns the response data, the last HTTP status code encountered, and any error.
func (c *Client) executeOnce(ctx context.Context, req *GraphQLRequest) (json.RawMessage, int, error) {
body, err := json.Marshal(req)
if err != nil {
return nil, 0, fmt.Errorf("failed to marshal request: %w", err)
}
var lastErr error
var lastStatus int
for attempt := 0; attempt <= MaxRetries; attempt++ {
if rlErr := c.circuitBreakerError(); rlErr != nil {
return nil, lastStatus, rlErr
}
httpReq, err := http.NewRequestWithContext(ctx, "POST", c.Endpoint, bytes.NewReader(body))
if err != nil {
return nil, 0, fmt.Errorf("failed to create request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
authValue, err := c.authHeader()
if err != nil {
return nil, 0, errView on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error to identify the offending field/type in the request variables
- Fix or remove the value that cannot be marshaled (cycle, unsupported type, invalid RawMessage)
- Validate custom MarshalJSON implementations on variable types
- Marshal the variables yourself beforehand to localize the failure before calling Execute
Example fix
// before
req := &linear.GraphQLRequest{Query: q, Variables: map[string]interface{}{"x": someChan}}
// after
vars, err := json.Marshal(map[string]interface{}{"x": "supported-value"})
if err != nil { return err } // catch it before the client does
req := &linear.GraphQLRequest{Query: q, Variables: parsedVars} Defensive patterns
Strategy: validation
Validate before calling
if raw, err := json.Marshal(req); err != nil {
return fmt.Errorf("request not serializable: %w", err)
} else if !json.Valid(raw) {
return fmt.Errorf("request marshaled to invalid JSON")
} Type guard
func isMarshalable(v interface{}) bool {
var mErr error
_ = json.Marshal // probe; real check:
mErr = marshalErr(v)
return mErr == nil
}
func marshalErr(v interface{}) error {
b, err := json.Marshal(v)
_ = b
return err
} Try / catch
data, err := client.Execute(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "failed to marshal request") {
return fmt.Errorf("bug: request variables unsupported by encoding/json: %w", err)
}
return err
} Prevention
- Keep GraphQL variables as JSON-safe types (string, number, bool, nil, maps, slices)
- Never pass channels, funcs, or cyclic structures as variables
- Pre-validate json.RawMessage payloads with json.Valid
- Add unit tests that marshal representative request payloads
When it happens
Trigger: Calling Execute with a GraphQLRequest whose Variables (or other fields) contain values json.Marshal cannot encode: json.RawMessage holding invalid JSON, cyclic data structures, unsupported types (chan, func, complex), or NaN/Inf float values.
Common situations: Passing variables built from dynamic data with cycles; injecting json.RawMessage from another marshal step that produced invalid bytes; custom types with a broken MarshalJSON implementation returning an error.
Related errors
- marshaling Linear milestone metadata: %w
- failed to marshal backup state: %w
- failed to marshal issue %s: %w
- failed to write JSON: %w
- existing milestone metadata is not a JSON object: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/30ca6ec06b52b896.
Report an issue: GitHub.