{"record":{"id":"01c318f80e79fe6c","repo":"github/github-mcp-server","slug":"failed-to-marshal-comment-w","errorCode":null,"errorMessage":"failed to marshal comment: %w","messagePattern":"failed to marshal comment: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/github/discussions.go","lineNumber":743,"sourceCode":"\t\tAddDiscussionComment struct {\n\t\t\tComment struct {\n\t\t\t\tID  githubv4.ID\n\t\t\t\tURL githubv4.String `graphql:\"url\"`\n\t\t\t}\n\t\t} `graphql:\"addDiscussionComment(input: $input)\"`\n\t}\n\n\tif err := client.Mutate(ctx, &mutation, input, nil); err != nil {\n\t\treturn utils.NewToolResultError(err.Error()), nil, nil\n\t}\n\n\tcomment := mutation.AddDiscussionComment.Comment\n\tout, err := json.Marshal(MinimalResponse{\n\t\tID:  fmt.Sprintf(\"%v\", comment.ID),\n\t\tURL: string(comment.URL),\n\t})\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to marshal comment: %w\", err)\n\t}\n\n\treturn utils.NewToolResultText(string(out)), nil, nil\n}\n\nfunc requiredCommentNodeID(args map[string]any) (string, error) {\n\tcommentNodeID, err := RequiredParam[string](args, \"commentNodeID\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif strings.TrimSpace(commentNodeID) == \"\" {\n\t\treturn \"\", fmt.Errorf(\"commentNodeID cannot be blank\")\n\t}\n\treturn commentNodeID, nil\n}\n\nfunc replyToDiscussionComment(ctx context.Context, client *githubv4.Client, args map[string]any) (*mcp.CallToolResult, any, error) {\n\tcommentNodeID, err := requiredCommentNodeID(args)","sourceCodeStart":725,"sourceCodeEnd":761,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/discussions.go#L725-L761","documentation":"After the add_discussion_comment mutation succeeds, the handler marshals MinimalResponse{ID string, URL string} — two fmt.Sprintf/string-converted fields. json.Marshal on a struct of two strings cannot fail in any Go version; this branch exists to satisfy error handling discipline, not because a real state produces it. If observed, the binary and source are out of sync or MinimalResponse was redefined to carry unmarshalable fields.","triggerScenarios":"Redefining MinimalResponse with a channel/func field or a custom MarshalJSON that errors; struct cycles if MinimalResponse ever embeds the comment object itself. No runtime input reaches this branch with the shipped two-string definition.","commonSituations":"Forks widening MinimalResponse for extra output; stale builds after editing minimal_types.go; custom build tags swapping the type. The mutation itself has already succeeded when this would fire, so the comment exists but the tool reports failure.","solutions":["Confirm MinimalResponse still contains only string fields; if extended, keep fields JSON-safe","Rebuild/redeploy if you edited response types — a mismatch between compiled binary and source is the likeliest cause","If extending the response, prefer explicit primitive fields over embedding graphqlv4 comment structs","Because the mutation succeeded upstream, treat any occurrence as report-worthy: the comment was created despite the error"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"out, err := json.Marshal(MinimalResponse{ID: id, URL: url})\nif err != nil {\n\t// mutation already committed; surface error but note possible false failure\n\treturn nil, nil, fmt.Errorf(\"failed to marshal comment: %w\", err)\n}","preventionTips":["Keep MinimalResponse limited to string fields","Never embed mutation structs into responses; copy out strings","Remember this error (if ever hit) implies the comment was created — check before retrying"],"tags":["go","json-marshal","defensive-code","discussions","mutations"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}