github/github-mcp-server · error

failed to marshal workflows: %w

Error message

failed to marshal workflows: %w

What it means

Defensive guard in listWorkflows (pkg/github/actions.go:839): json.Marshal of the *github.WorkflowList (the whole workflows array from ListWorkflows) failed. The list is server-produced JSON-safe data, so this is effectively unreachable except through a regression introducing non-serializable values; the body is closed via defer before marshal, so it is purely a serialization guard.

Source

Thrown at pkg/github/actions.go:839

	}
	return utils.NewToolResultText(string(r)), nil, nil
}

func listWorkflows(ctx context.Context, client *github.Client, owner, repo string, pagination PaginationParams) (*mcp.CallToolResult, any, error) {
	opts := &github.ListOptions{
		PerPage: pagination.PerPage,
		Page:    pagination.Page,
	}

	workflows, resp, err := client.Actions.ListWorkflows(ctx, owner, repo, opts)
	if err != nil {
		return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to list workflows", resp, err), nil, nil
	}
	defer func() { _ = resp.Body.Close() }()

	r, err := json.Marshal(workflows)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to marshal workflows: %w", err)
	}

	return utils.NewToolResultText(string(r)), nil, nil
}

func listWorkflowRuns(ctx context.Context, client *github.Client, args map[string]any, owner, repo, resourceID string, pagination PaginationParams) (*mcp.CallToolResult, any, error) {
	filterArgs, err := OptionalParam[map[string]any](args, "workflow_runs_filter")
	if err != nil {
		return utils.NewToolResultError(err.Error()), nil, nil
	}

	filterArgsTyped := make(map[string]string)
	for k, v := range filterArgs {
		if strVal, ok := v.(string); ok {
			filterArgsTyped[k] = strVal
		} else {
			filterArgsTyped[k] = ""
		}

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Report upstream with repository and versions if hit with stock code
  2. Pin dependencies to known-good versions
  3. If maintaining a fork, keep PaginationParams sane and avoid injecting custom objects into results
  4. Add a marshal test over representative list responses

Example fix

// before
r, err := json.Marshal(workflows)
if err != nil {
    return nil, nil, fmt.Errorf("failed to marshal workflows: %w", err)
}

// after - include count context to speed up diagnosis
r, err := json.Marshal(workflows)
if err != nil {
    return nil, nil, fmt.Errorf("failed to marshal workflows (count=%d): %w", len(workflows.Workflows), err)
}
Defensive patterns

Strategy: validation

Validate before calling

// Test-side guard over list responses
func TestWorkflowListMarshal(t *testing.T) {
    if _, err := json.Marshal(&github.WorkflowList{}); err != nil {
        t.Fatalf("workflow list not JSON-safe: %v", err)
    }
}

Try / catch

if err != nil {
    reportIssue("list_action_workflows", map[string]any{"owner": owner, "repo": repo}, err, version())
    return err
}

Prevention

When it happens

Trigger: Calling list_action_workflows after a dependency change that makes Workflow or WorkflowList unmarshalable; huge result sets are not a failure cause - json.Marshal handles arbitrary size, only value types matter.

Common situations: Not seen with stock releases; appears in heavily forked servers or with replace-directive go-github builds.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/e05b0786e3e34c62. Report an issue: GitHub.