github/github-mcp-server · warning
failed to marshal discussions: %w
Error message
failed to marshal discussions: %w
What it means
After the list_discussions GraphQL query succeeds, the handler assembles a response map (discussions slice, pageInfo strings/bools, totalCount int) and json.Marshals it. json.Marshal only errors on unsupported values (channels, functions, complex numbers, NaN/Inf floats) or cyclic references; every field here is a plain string/bool/int derived from GraphQL scalars, so this path is defensive and effectively unreachable in practice. If it ever fires, a schema/type change introduced an unmarshalable value.
Source
Thrown at pkg/github/discussions.go:274
pageInfo = fragment.PageInfo
totalCount = fragment.TotalCount
}
// Create response with pagination info
response := map[string]any{
"discussions": discussions,
"pageInfo": map[string]any{
"hasNextPage": pageInfo.HasNextPage,
"hasPreviousPage": pageInfo.HasPreviousPage,
"startCursor": string(pageInfo.StartCursor),
"endCursor": string(pageInfo.EndCursor),
},
"totalCount": totalCount,
}
out, err := json.Marshal(response)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal discussions: %w", err)
}
result := utils.NewToolResultText(string(out))
// Discussion content is user-authored (untrusted); confidentiality
// follows repo visibility.
result = attachRepoVisibilityIFCLabelLazy(ctx, deps, owner, repo, result, ifc.LabelRepoUserContent)
return result, nil, nil
},
)
}
func GetDiscussion(t translations.TranslationHelperFunc) inventory.ServerTool {
return NewTool(
ToolsetMetadataDiscussions,
mcp.Tool{
Name: "get_discussion",
Description: t("TOOL_GET_DISCUSSION_DESCRIPTION", "Get a specific discussion by ID"),
Annotations: &mcp.ToolAnnotations{
Title: t("TOOL_GET_DISCUSSION_USER_TITLE", "Get discussion"),View on GitHub (pinned to 0ea1f775a7)
Solutions
- Treat a hit as a code defect: inspect the discussions slice's element types for funcs, channels, or custom MarshalJSON implementations
- Add a unit test that marshals a representative response map to catch type regressions in CI
- Keep the response composed of primitives (string/int/bool) as it is today
- If hit in production, log the payload types (not contents) and fall back to a minimal shape so the tool still returns something useful
Defensive patterns
Strategy: try-catch
Try / catch
out, err := json.Marshal(response)
if err != nil {
// defensive branch: a failure means a code defect in response construction
logger.Error("marshal discussions failed", "err", err)
return nil, nil, fmt.Errorf("failed to marshal discussions: %w", err)
} Prevention
- Keep response maps composed of string/int/bool primitives
- Convert GraphQL scalars (githubv4.ID, githubv4.URI) to strings before insertion
- Add golden JSON tests per tool response shape to catch type regressions in CI
When it happens
Trigger: A future change storing a githubv4.ID, time.Time with a bad MarshalJSON, or a func/channel inside the discussions slice or pageInfo map; cyclic structures if discussion objects ever reference each other. Not triggerable by any GitHub API response with the current types.
Common situations: Refactors that swap plain strings for typed wrappers with custom marshaling bugs; test code mutating the response shape; library forks adding fields. Real GitHub data (titles, cursors, counts) cannot cause it.
Related errors
- failed to marshal discussion: %w
- failed to marshal comments: %w
- failed to marshal comment: %w
- failed to marshal discussion categories: %w
- failed to marshal response: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/3a5568b731ca702d.
Report an issue: GitHub.