gastownhall/beads · error
marshal create request: %w
Error message
marshal create request: %w
What it means
CreateIssue wraps json.Marshal failures when encoding {"fields": ...} from the caller-supplied map. json.Marshal of a map[string]interface{} only fails for values JSON cannot represent: channels, funcs, complex numbers, or cyclic references. The library throws it because the request payload cannot be built at all.
Source
Thrown at internal/jira/client.go:258
if err != nil {
return nil, fmt.Errorf("get issue %s: %w", key, err)
}
var issue Issue
if err := json.Unmarshal(body, &issue); err != nil {
return nil, fmt.Errorf("parse issue response: %w", err)
}
return &issue, nil
}
// CreateIssue creates a new issue in Jira.
// fields should include "project", "summary", "issuetype", and optionally other fields.
func (c *Client) CreateIssue(ctx context.Context, fields map[string]interface{}) (*Issue, error) {
payload := map[string]interface{}{"fields": fields}
data, err := json.Marshal(payload)
if err != nil {
return nil, fmt.Errorf("marshal create request: %w", err)
}
apiURL := fmt.Sprintf("%s/issue", c.apiBase())
body, err := c.doRequest(ctx, "POST", apiURL, data)
if err != nil {
return nil, fmt.Errorf("create issue: %w", err)
}
// Create response only returns id, key, self. Fetch the full issue.
var created struct {
ID string `json:"id"`
Key string `json:"key"`
Self string `json:"self"`
}
if err := json.Unmarshal(body, &created); err != nil {
return nil, fmt.Errorf("parse create response: %w", err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Audit the fields map values: remove or convert channels, funcs, and complex types to JSON-safe values.
- Use json.RawMessage or explicit structs for custom/complex field values.
- Marshal the fields map alone in a test to find the offending key quickly.
- Prefer typed structs over map[string]interface{} for request bodies so invalid values fail at compile time.
Example fix
// before: unsupported value slips in
fields := map[string]interface{}{
"project": map[string]string{"key": "PROJ"},
"customfield": someChannel, // json: unsupported type
}
// after: only JSON-encodable values
fields := map[string]interface{}{
"project": map[string]string{"key": "PROJ"},
"customfield": "string-value",
} Defensive patterns
Strategy: validation
Validate before calling
// Fail fast on non-serializable values before calling the API:
func validateFields(fields map[string]interface{}) error {
for k, v := range fields {
switch v.(type) {
case chan interface{}, func(), complex128, map[interface{}]interface{}:
return fmt.Errorf("field %q has non-JSON-encodable type %T", k, v)
}
}
_, err := json.Marshal(fields)
return err
} Type guard
func jsonEncodable(v interface{}) bool {
_, err := json.Marshal(v)
return err == nil
} Try / catch
issue, err := client.CreateIssue(ctx, fields)
if err != nil && strings.Contains(err.Error(), "marshal create request") {
// non-serializable value in fields: no request was sent, safe to fix and retry
for k, v := range fields {
if !jsonEncodable(v) {
log.Printf("field %q (%T) is not JSON-encodable", k, v)
}
}
return
} Prevention
- Use typed structs instead of map[string]interface{} for field values
- Run validateFields(fields) in unit tests for every issue-creation code path
- Never store funcs/channels/loggers in the fields map
- Use json.RawMessage for pre-serialized custom field values
When it happens
Trigger: Passing a fields map containing a non-serializable value (e.g. a func, channel, or a custom struct with unexported-only/cyclic data) as any field value in CreateIssue.
Common situations: Building fields programmatically where a variable of type interface{} holds an unsupported runtime type; accidental inclusion of a logger or callback in the map; custom field values sourced from reflection-heavy code.
Related errors
- failed to marshal backup state: %w
- failed to marshal issue %s: %w
- failed to marshal interactions log entry: %w
- parse Jira response: %w
- parse search response: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ae18f50e65c302c0.
Report an issue: GitHub.