{"record":{"id":"ae18f50e65c302c0","repo":"gastownhall/beads","slug":"marshal-create-request-w","errorCode":null,"errorMessage":"marshal create request: %w","messagePattern":"marshal create request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/jira/client.go","lineNumber":258,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get issue %s: %w\", key, err)\n\t}\n\n\tvar issue Issue\n\tif err := json.Unmarshal(body, &issue); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse issue response: %w\", err)\n\t}\n\n\treturn &issue, nil\n}\n\n// CreateIssue creates a new issue in Jira.\n// fields should include \"project\", \"summary\", \"issuetype\", and optionally other fields.\nfunc (c *Client) CreateIssue(ctx context.Context, fields map[string]interface{}) (*Issue, error) {\n\tpayload := map[string]interface{}{\"fields\": fields}\n\tdata, err := json.Marshal(payload)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal create request: %w\", err)\n\t}\n\n\tapiURL := fmt.Sprintf(\"%s/issue\", c.apiBase())\n\n\tbody, err := c.doRequest(ctx, \"POST\", apiURL, data)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create issue: %w\", err)\n\t}\n\n\t// Create response only returns id, key, self. Fetch the full issue.\n\tvar created struct {\n\t\tID   string `json:\"id\"`\n\t\tKey  string `json:\"key\"`\n\t\tSelf string `json:\"self\"`\n\t}\n\tif err := json.Unmarshal(body, &created); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse create response: %w\", err)\n\t}","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/jira/client.go#L240-L276","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: unsupported value slips in\nfields := map[string]interface{}{\n    \"project\":     map[string]string{\"key\": \"PROJ\"},\n    \"customfield\": someChannel, // json: unsupported type\n}\n// after: only JSON-encodable values\nfields := map[string]interface{}{\n    \"project\":     map[string]string{\"key\": \"PROJ\"},\n    \"customfield\": \"string-value\",\n}","handlingStrategy":"validation","validationCode":"// Fail fast on non-serializable values before calling the API:\nfunc validateFields(fields map[string]interface{}) error {\n    for k, v := range fields {\n        switch v.(type) {\n        case chan interface{}, func(), complex128, map[interface{}]interface{}:\n            return fmt.Errorf(\"field %q has non-JSON-encodable type %T\", k, v)\n        }\n    }\n    _, err := json.Marshal(fields)\n    return err\n}","typeGuard":"func jsonEncodable(v interface{}) bool {\n    _, err := json.Marshal(v)\n    return err == nil\n}","tryCatchPattern":"issue, err := client.CreateIssue(ctx, fields)\nif err != nil && strings.Contains(err.Error(), \"marshal create request\") {\n    // non-serializable value in fields: no request was sent, safe to fix and retry\n    for k, v := range fields {\n        if !jsonEncodable(v) {\n            log.Printf(\"field %q (%T) is not JSON-encodable\", k, v)\n        }\n    }\n    return\n}","preventionTips":["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"],"tags":["jira","json","serialization","go"],"backgroundTag":"json-marshal-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}