argoproj/argo-workflows · info

failed to marshal patch: %w

Error message

failed to marshal patch: %w

What it means

In archiveWorkflowAux (workflow/controller/controller.go:1417), after successfully archiving, the controller builds a JSON merge patch setting the workflows.argoproj.io/archiving-status label to Archived. This error means json.Marshal of that tiny static map failed — practically unreachable with the hardcoded map (json.Marshal only fails on unsupported types), so it indicates an exotic build/runtime anomaly rather than a user-fixable condition.

Source

Thrown at workflow/controller/controller.go:1417

	err = wfc.hydrator.Hydrate(ctx, wf)
	if err != nil {
		return fmt.Errorf("failed to hydrate workflow: %w", err)
	}
	logger := logging.RequireLoggerFromContext(ctx)
	logger.WithFields(logging.Fields{"namespace": wf.Namespace, "workflow": wf.Name, "uid": wf.UID}).Info(ctx, "archiving workflow")
	err = wfc.wfArchive.ArchiveWorkflow(ctx, wf)
	if err != nil {
		return fmt.Errorf("failed to archive workflow: %w", err)
	}
	data, err := json.Marshal(map[string]any{
		"metadata": metav1.ObjectMeta{
			Labels: map[string]string{
				common.LabelKeyWorkflowArchivingStatus: "Archived",
			},
		},
	})
	if err != nil {
		return fmt.Errorf("failed to marshal patch: %w", err)
	}
	_, err = wfc.wfclientset.ArgoprojV1alpha1().Workflows(un.GetNamespace()).Patch(
		ctx,
		un.GetName(),
		types.MergePatchType,
		data,
		metav1.PatchOptions{},
	)
	if err != nil {
		// from this point on we have successfully archived the workflow, and it is possible for the workflow to have actually
		// been deleted, so it's not a problem to get a `IsNotFound` error
		if apierr.IsNotFound(err) {
			return nil
		}
		return fmt.Errorf("failed to mark the workflow archived: %w", err)
	}
	return nil
}

View on GitHub (pinned to 35bff19146)

Solutions

  1. If you forked and changed the patch payload, ensure all values are JSON-serializable (use string labels, plain maps).
  2. Rebuild the controller binary from unmodified upstream sources.
  3. If reproducible, capture the inner marshal error via the wrapped %w chain and file an issue.

Example fix

// before (forked payload with unsupported type)
data, err := json.Marshal(map[string]any{"metadata": metav1.ObjectMeta{Labels: map[string]string{...}, ManagedFields: someFunc}})
// after
un, _ := signaling.ObjectMapper.ObjectToUnstructured(...)
data, err := json.Marshal(map[string]any{"metadata": metav1.ObjectMeta{Labels: map[string]string{common.LabelKeyWorkflowArchivingStatus: "Archived"}}})
Defensive patterns

Strategy: try-catch

Try / catch

data, err := json.Marshal(map[string]any{
    "metadata": metav1.ObjectMeta{Labels: map[string]string{common.LabelKeyWorkflowArchivingStatus: "Archived"}},
})
if err != nil {
    return fmt.Errorf("failed to marshal patch: %w", err)
}

Prevention

When it happens

Trigger: json.Marshal(map[string]any{"metadata": metav1.ObjectMeta{...}}) returns an error — with the fixed literal payload this should never happen; only conceivable via a corrupted standard library/runtime or if the literal was modified to include non-serializable values (channels/funcs) in a fork.

Common situations: Only in modified/forked code where the patch payload includes unsupported types; no real-world cluster configuration triggers it.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/5583c7a71adec26a. Report an issue: GitHub.