github/github-mcp-server · error

failed to marshal workflow jobs: %w

Error message

failed to marshal workflow jobs: %w

What it means

json.Marshal failed on the {"jobs": convertToMinimalWorkflowJobs(...)} response map built after a successful workflow-jobs listing. encoding/json errors only occur for values it cannot encode (chan, func, complex, cyclic structures, NaN/Inf floats). Since the map holds a slice of trimmed job structs made of strings, ints and timestamps, the failure indicates the converted data contains an unsupported value rather than a GitHub API problem.

Source

Thrown at pkg/github/actions.go:928

	workflowJobs, resp, err := client.Actions.ListWorkflowJobs(ctx, owner, repo, resourceID, &github.ListWorkflowJobsOptions{
		Filter: filterArgsTyped["filter"],
		ListOptions: github.ListOptions{
			Page:    pagination.Page,
			PerPage: pagination.PerPage,
		},
	})
	if err != nil {
		return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to list workflow jobs", resp, err), nil, nil
	}

	response := map[string]any{
		"jobs": convertToMinimalWorkflowJobs(workflowJobs),
	}

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

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

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

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

	r, err := json.Marshal(artifacts)

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Read the wrapped json.UnsupportedTypeError/UnsupportedValueError to find the offending field and type, then drop or stringify it in convertToMinimalWorkflowJobs
  2. Align go-github and github-mcp-server versions so job structs match the live API
  3. Pre-sanitize the jobs slice (only keep string/number/bool/time fields) before marshaling
  4. Retry the call to exclude transient corruption

Example fix

// before
response := map[string]any{"jobs": convertToMinimalWorkflowJobs(workflowJobs)}
r, err := json.Marshal(response)
if err != nil {
	return nil, nil, fmt.Errorf("failed to marshal workflow jobs: %w", err)
}

// after — guard and report without crashing the tool
doc := map[string]any{"jobs": convertToMinimalWorkflowJobs(workflowJobs)}
r, err := json.Marshal(doc)
if err != nil {
	return utils.NewToolResultError(fmt.Sprintf("failed to serialize workflow jobs: %v", err)), nil, nil
}
Defensive patterns

Strategy: try-catch

Type guard

func jobsAreJSONSafe(jobs []map[string]any) bool {
	for _, j := range jobs {
		for _, v := range j {
			switch v.(type) {
			case chan struct{}, func(), complex128, complex64:
				return false
			}
		}
	}
	return true
}

Try / catch

r, err := json.Marshal(response)
if err != nil {
	var unsupported *json.UnsupportedTypeError
	if errors.As(err, &unsupported) {
		// strip or stringify unsupported.Type, rebuild the response map, retry marshal once
	}
	return fmt.Errorf("failed to marshal workflow jobs: %w", err)
}

Prevention

When it happens

Trigger: Calling list_workflow_jobs for a run and having the minimal-jobs converter emit a non-JSON-representable value — typically after upgrading go-github so a new field of an unsupported type flows through convertToMinimalWorkflowJobs, or a fork adds such a field.

Common situations: Dependency drift between go-github and the server's converter functions, custom converters extended with io.Reader or func fields, corrupted pagination data after a truncated API response.

Related errors


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