github/github-mcp-server · error
failed to marshal workflow run: %w
Error message
failed to marshal workflow run: %w
What it means
Defensive guard in getWorkflowRun (pkg/github/actions.go:807): json.Marshal of convertToMinimalWorkflowRun(workflowRun) failed. The conversion produces a server-owned minimal struct of scalar fields, so this is effectively unreachable unless a regression adds a non-serializable value (func, chan, NaN, cycle) to that struct.
Source
Thrown at pkg/github/actions.go:807
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
}
func getWorkflowJob(ctx context.Context, client *github.Client, owner, repo string, resourceID int64) (*mcp.CallToolResult, any, error) {
workflowJob, resp, err := client.Actions.GetWorkflowJobByID(ctx, owner, repo, resourceID)
if err != nil {
return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to get workflow job", resp, err), nil, nil
}
defer func() { _ = resp.Body.Close() }()
r, err := json.Marshal(workflowJob)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal workflow job: %w", err)
}
return utils.NewToolResultText(string(r)), nil, nil
}
func listWorkflows(ctx context.Context, client *github.Client, owner, repo string, pagination PaginationParams) (*mcp.CallToolResult, any, error) {View on GitHub (pinned to 0ea1f775a7)
Solutions
- Report upstream if hit with a stock release - include run ID and versions
- Keep the minimal struct scalar-only (string, int, bool, time as string)
- Unit-test the conversion plus marshal path
- Pin known-good versions
Example fix
// before
r, err := json.Marshal(convertToMinimalWorkflowRun(workflowRun))
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal workflow run: %w", err)
}
// after - guard the conversion itself with a test-friendly error
minimal := convertToMinimalWorkflowRun(workflowRun)
r, err := json.Marshal(minimal)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal workflow run (run %d): %w", workflowRun.GetID(), err)
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the converted struct is JSON-safe in tests
func TestMinimalWorkflowRunMarshal(t *testing.T) {
if _, err := json.Marshal(convertToMinimalWorkflowRun(&github.WorkflowRun{})); err != nil {
t.Fatalf("minimal run not JSON-safe: %v", err)
}
} Try / catch
if err != nil {
reportIssue("get_action_workflow_run", map[string]any{"run_id": runID}, err, version())
return err
} Prevention
- Keep converted structs scalar-only
- Format times as strings in DTOs
- Pin versions; watch changelogs for serialization fixes
- Do not retry deterministic marshal failures
When it happens
Trigger: Calling get_action_workflow_run with a valid run ID after code changes made convertToMinimalWorkflowRun emit JSON-unsafe values; NaN timestamps/durations introduced by timezone or duration math bugs.
Common situations: Not seen in stock releases; a hazard only for forks that extend the minimal-run struct.
Related errors
- 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
- failed to marshal workflow: %w
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/2304f9b46a097e31.
Report an issue: GitHub.