github/github-mcp-server · error

failed to marshal workflow runs: %w

Error message

failed to marshal workflow runs: %w

What it means

json.Marshal failed while serializing the trimmed workflow-run list produced by convertToMinimalWorkflowRuns after a successful ListWorkflowRunsByID/ListWorkflowRunsByFileName call. encoding/json only fails on values it cannot represent: channels, functions, complex numbers, cyclic data structures, or float NaN/Inf (json.UnsupportedTypeError / json.UnsupportedValueError). Because the payload is maps/structs of strings, ints and timestamps built from go-github types, this branch is defensive and should never fire on a healthy release.

Source

Thrown at pkg/github/actions.go:889

	var workflowRuns *github.WorkflowRuns
	var resp *github.Response

	if resourceID == "" {
		workflowRuns, resp, err = client.Actions.ListRepositoryWorkflowRuns(ctx, owner, repo, listWorkflowRunsOptions)
	} else if workflowIDInt, parseErr := strconv.ParseInt(resourceID, 10, 64); parseErr == nil {
		workflowRuns, resp, err = client.Actions.ListWorkflowRunsByID(ctx, owner, repo, workflowIDInt, listWorkflowRunsOptions)
	} else {
		workflowRuns, resp, err = client.Actions.ListWorkflowRunsByFileName(ctx, owner, repo, resourceID, listWorkflowRunsOptions)
	}

	if err != nil {
		return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to list workflow runs", resp, err), nil, nil
	}

	defer func() { _ = resp.Body.Close() }()
	r, err := json.Marshal(convertToMinimalWorkflowRuns(workflowRuns))
	if err != nil {
		return nil, nil, fmt.Errorf("failed to marshal workflow runs: %w", err)
	}

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

func listWorkflowJobs(ctx context.Context, client *github.Client, args map[string]any, owner, repo string, resourceID int64, pagination PaginationParams) (*mcp.CallToolResult, any, error) {
	filterArgs, err := OptionalParam[map[string]any](args, "workflow_jobs_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. Inspect the wrapped error: json.UnsupportedTypeError names the exact Go type and field path that broke marshaling — fix or stringify that field in convertToMinimalWorkflowRuns
  2. Update the go-github dependency and github-mcp-server to matching versions so the struct shape matches what GitHub returns
  3. Sanitize the converted runs before marshaling (drop or fmt.Sprintf non-JSON types, clamp NaN/Inf floats)
  4. Re-run the tool once to rule out a one-off corrupted response

Example fix

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

// after — surface the offending type and return a tool-safe error
runs := convertToMinimalWorkflowRuns(workflowRuns)
r, err := json.Marshal(runs)
if err != nil {
	var unsupported *json.UnsupportedTypeError
	if errors.As(err, &unsupported) {
		slog.Error("unmarshalable workflow run payload", "type", unsupported.Type.String())
	}
	return utils.NewToolResultError(fmt.Sprintf("failed to serialize workflow runs: %v", err)), nil, nil
}
Defensive patterns

Strategy: try-catch

Type guard

func isJSONMarshalable(v any) bool {
	switch v.(type) {
	case chan struct{}, func(), complex128, complex64:
		return false
	}
	return true
}

Try / catch

r, err := json.Marshal(runs)
if err != nil {
	var unsupported *json.UnsupportedTypeError
	var value *json.UnsupportedValueError
	switch {
	case errors.As(err, &unsupported):
		// upstream type drift: log unsupported.Type and degrade gracefully
	case errors.As(err, &value):
		// NaN/Inf: sanitize numeric fields and retry once
	default:
		return fmt.Errorf("failed to marshal workflow runs: %w", err)
	}
}

Prevention

When it happens

Trigger: Calling list_workflow_runs (or list_workflow_runs_by_filename) and reaching the final json.Marshal with a payload containing a non-JSON-representable value — e.g. an upstream go-github version bump that added a func/chan/complex-typed field copied through the minimal-runs converter, or a fork that passes timestamps.Float64 values that are NaN.

Common situations: Pinned/old go-github dependency whose structs diverge from the API payload, custom forks extending convertToMinimalWorkflowRuns with unsupported types, or corrupted in-memory data after a partial API response.

Related errors


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