github/github-mcp-server · error
failed to marshal workflow: %w
Error message
failed to marshal workflow: %w
What it means
Defensive guard in getWorkflow (pkg/github/actions.go:793): json.Marshal of a *github.Workflow returned by GetWorkflowByID or GetWorkflowByFileName failed. go-github structs are plain JSON-safe data types, so this is effectively unreachable unless the struct contains a non-serializable field (func, chan, NaN, cycle) - which would be a go-github or server regression, not caller input.
Source
Thrown at pkg/github/actions.go:793
func getWorkflow(ctx context.Context, client *github.Client, owner, repo, resourceID string) (*mcp.CallToolResult, any, error) {
var workflow *github.Workflow
var resp *github.Response
var err error
if workflowIDInt, parseErr := strconv.ParseInt(resourceID, 10, 64); parseErr == nil {
workflow, resp, err = client.Actions.GetWorkflowByID(ctx, owner, repo, workflowIDInt)
} else {
workflow, resp, err = client.Actions.GetWorkflowByFileName(ctx, owner, repo, resourceID)
}
if err != nil {
return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to get workflow", resp, err), nil, nil
}
defer func() { _ = resp.Body.Close() }()
r, err := json.Marshal(workflow)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal workflow: %w", err)
}
return utils.NewToolResultText(string(r)), nil, nil
}
func getWorkflowRun(ctx context.Context, client *github.Client, owner, repo string, resourceID int64) (*mcp.CallToolResult, any, error) {
workflowRun, resp, err := client.Actions.GetWorkflowRunByID(ctx, owner, repo, resourceID)
if err != nil {
return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to get workflow run", resp, err), nil, nil
}
defer func() { _ = resp.Body.Close() }()
r, err := json.Marshal(convertToMinimalWorkflowRun(workflowRun))
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal workflow run: %w", err)
}
return utils.NewToolResultText(string(r)), nil, nil
}
View on GitHub (pinned to 0ea1f775a7)
Solutions
- Report upstream with the exact arguments and versions - input cannot trigger it
- Pin go-github and github-mcp-server to known-good versions
- If patching, marshal a minimal DTO instead of the raw struct
- Add a regression test marshaling the struct shape
Example fix
// before
r, err := json.Marshal(workflow)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal workflow: %w", err)
}
// after - marshal a stable DTO to decouple from go-github struct churn
minimal := map[string]any{
"id": workflow.GetID(), "name": workflow.GetName(), "path": workflow.GetPath(), "state": workflow.GetState(),
}
r, err := json.Marshal(minimal) Defensive patterns
Strategy: validation
Validate before calling
// Maintainer-side: keep the marshaled payload JSON-safe
if _, err := json.Marshal(workflow); err != nil {
return fmt.Errorf("workflow not JSON-safe before tool return: %w", err)
} Try / catch
if err != nil {
// deterministic serialization failure: report, never retry
reportIssue("get_action_workflow", args, err, version())
return err
} Prevention
- Pin go-github and github-mcp-server versions
- Marshal-test API structs in CI after dependency upgrades
- Prefer marshaling minimal DTOs over raw library structs
- Treat this error as a bug signature, not an operational condition
When it happens
Trigger: Calling get_action_workflow (by numeric ID or by .yml file name) after a go-github upgrade that introduced a JSON-unsafe field; fork modifications embedding non-serializable state in the workflow struct.
Common situations: Virtually never in stock deployments; appears in forks or after unusual dependency versions.
Related errors
- failed to marshal workflows: %w
- GitHub App authentication and GITHUB_PERSONAL_ACCESS_TOKEN a
- GitHub App ID or client ID is required (GITHUB_APP_ID)
- repo is required
- failed to marshal response: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/975787228e81c9bd.
Report an issue: GitHub.