gastownhall/beads · error
marshal request body: %w
Error message
marshal request body: %w
What it means
doRequest could not JSON-serialize the request payload passed as requestBody. The error wraps the json.Marshal error, so the underlying cause (unsupported type, channel/func field, invalid value) is in the chain. It fires only when requestBody != nil.
Source
Thrown at internal/notion/client.go:260
}
func (c *Client) doRequest(ctx context.Context, method, path string, requestBody interface{}) ([]byte, error) {
if c == nil {
return nil, fmt.Errorf("notion client is nil")
}
if strings.TrimSpace(c.Token) == "" {
return nil, fmt.Errorf("Notion token not configured")
}
httpClient := c.HTTPClient
if httpClient == nil {
httpClient = &http.Client{Timeout: DefaultTimeout}
}
var bodyReader io.Reader
if requestBody != nil {
payload, err := json.Marshal(requestBody)
if err != nil {
return nil, fmt.Errorf("marshal request body: %w", err)
}
bodyReader = bytes.NewReader(payload)
}
requestURL := path
if !strings.HasPrefix(requestURL, "http://") && !strings.HasPrefix(requestURL, "https://") {
requestURL = strings.TrimSuffix(c.BaseURL, "/") + path
}
req, err := http.NewRequestWithContext(ctx, method, requestURL, bodyReader)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+c.Token)
req.Header.Set("Notion-Version", c.NotionVersion)
req.Header.Set("Accept", "application/json")
if requestBody != nil {
req.Header.Set("Content-Type", "application/json")
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error (%w chain) to identify the offending field/type reported by encoding/json.
- Ensure requestBody is a plain JSON-serializable struct/map with exported fields and proper json tags.
- Marshal it yourself first in a test: b, err := json.Marshal(req); check err to reproduce locally.
- Set the field to omitempty or remove unsupported fields from the request type.
Example fix
// before
type req struct {
Callback func() `json:"callback"`
}
client.Query(ctx, req{Callback: fn}) // marshal error
// after
type req struct {
Name string `json:"name"`
}
client.Query(ctx, req{Name: "x"}) Defensive patterns
Strategy: validation
Validate before calling
if requestBody != nil {
if _, err := json.Marshal(requestBody); err != nil {
return fmt.Errorf("invalid request body: %w", err)
}
} Try / catch
if err != nil && strings.Contains(err.Error(), "marshal request body") {
log.Printf("request body not JSON-serializable: %v", err)
} Prevention
- Use typed request structs with exported fields and json tags instead of ad-hoc maps/interface{}.
- Keep channels, funcs, and complex numbers out of request types.
- Add unit tests that json.Marshal every request payload your code builds.
When it happens
Trigger: Passing a requestBody containing values json cannot encode: a struct field of type chan, func, or complex; an unexported-fields-only struct (marshals but often fine) or types with custom MarshalJSON that return errors; passing a map with non-string keys of an unsupported kind.
Common situations: Users build the request struct with a field typed as interface{} holding a channel or func; copy-pasted types with json:"-"-style custom marshaling gone wrong; passing *time.Time wrappers with bad MarshalJSON implementations.
Related errors
- failed to marshal backup state: %w
- failed to marshal issue %s: %w
- failed to write JSON: %w
- marshaling Linear milestone metadata: %w
- failed to marshal interactions log entry: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/63aebdd0bddcacfc.
Report an issue: GitHub.