{"record":{"id":"276bfa3587983fac","repo":"chenhg5/cc-connect","slug":"marshal-w","errorCode":null,"errorMessage":"marshal: %w","messagePattern":"marshal: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/claudecode/session.go","lineNumber":1095,"sourceCode":"\t\t\"type\": \"control_response\",\n\t\t\"response\": map[string]any{\n\t\t\t\"subtype\":    \"success\",\n\t\t\t\"request_id\": requestID,\n\t\t\t\"response\":   permResponse,\n\t\t},\n\t}\n\n\tslog.Debug(\"claudeSession: permission response\", \"request_id\", requestID, \"behavior\", result.Behavior)\n\treturn cs.writeJSON(controlResponse)\n}\n\nfunc (cs *claudeSession) writeJSON(v any) error {\n\tcs.stdinMu.Lock()\n\tdefer cs.stdinMu.Unlock()\n\n\tdata, err := json.Marshal(v)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshal: %w\", err)\n\t}\n\tif _, err := cs.stdin.Write(append(data, '\\n')); err != nil {\n\t\treturn fmt.Errorf(\"write stdin: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc isClaudeEditTool(toolName string) bool {\n\tswitch toolName {\n\tcase \"Edit\", \"Write\", \"NotebookEdit\", \"MultiEdit\":\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (cs *claudeSession) setPermissionMode(mode string) {\n\tcs.permissionMode.Store(mode)","sourceCodeStart":1077,"sourceCodeEnd":1113,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/claudecode/session.go#L1077-L1113","documentation":"writeJSON wraps a json.Marshal failure as 'marshal: %w'. The payload constructed by Send (user message with images/files) or RespondPermission (permission result) could not be serialized to JSON. In practice this is rare for these structurally-typed maps and usually indicates non-serializable values injected into the payload (e.g. NaN/infinite floats, channels, funcs) via UpdatedInput or attachments.","triggerScenarios":"Send with images/files whose metadata fields contain unsupported types; RespondPermission with result.UpdatedInput populated from parsed tool input containing values json.Marshal rejects (NaN, cyclic structures, func values).","commonSituations":"Tool input round-tripped through custom parsers storing unusual types; plugins/agent code inserting unsupported values into UpdatedInput; custom image/file attachment structs with non-serializable fields.","solutions":["Inspect the wrapped error's path (json.UnsupportedTypeError names the field) and sanitize/convert that value to a serializable type (string, float64, etc.)","In RespondPermission, ensure UpdatedInput only carries map[string]any / primitives — coerce or drop exotic values before assigning","Log the payload type at debug level to find which caller (Send vs RespondPermission) produced the bad value","Fix at the source: validate permission results before calling RespondPermission"],"exampleFix":"// before\nresult.UpdatedInput = rawToolInput // may contain NaN / unsupported types\n// after\nsafe, err := sanitizeJSONValue(rawToolInput)\nif err != nil {\n    return fmt.Errorf(\"sanitize updated input: %w\", err)\n}\nresult.UpdatedInput = safe","handlingStrategy":"validation","validationCode":"// validate payloads are JSON-safe before calling Send/RespondPermission\nfunc jsonSafe(v any) error {\n    _, err := json.Marshal(v)\n    return err // surfaces UnsupportedTypeError with the offending path\n}\n// usage: if err := jsonSafe(result.UpdatedInput); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := sess.RespondPermission(reqID, result); err != nil {\n    var ue *json.UnsupportedTypeError\n    if errors.As(err, &ue) && strings.Contains(err.Error(), \"marshal\") {\n        log.Warn(\"non-serializable value in permission result\", \"field\", ue.Value)\n        result.UpdatedInput = coerceToPrimitives(result.UpdatedInput)\n        err = sess.RespondPermission(reqID, result)\n    }\n}","preventionTips":["Restrict UpdatedInput and attachment metadata to map[string]any with primitives","Never pass values produced by decoding into interface{} straight from binary/custom formats without coercion","Sanitize floats (reject NaN/Inf) before building payloads","Round-trip test permission payloads with json.Marshal in unit tests"],"tags":["go","json","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}